Command.cpp revision eaeb19048672337714c1724de7992be8cb3f2124
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"
10b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet#include "Images.h"
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "XMLNode.h"
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
133b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/Log.h>
143b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/threads.h>
153b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/List.h>
163b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/Errors.h>
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Show version info.  All the cool kids do it.
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doVersion(Bundle* bundle)
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() != 0)
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("(ignoring extra arguments)\n");
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("Android Asset Packaging Tool, v0.2\n");
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open the file read only.  The call fails if the file doesn't exist.
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns NULL on failure.
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFile* openReadOnly(const char* fileName)
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new ZipFile;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = zip->open(fileName, ZipFile::kOpenReadOnly);
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result == NAME_NOT_FOUND)
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: '%s' not found\n", fileName);
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (result == PERMISSION_DENIED)
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: '%s' access denied\n", fileName);
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n",
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fileName);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete zip;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Open the file read-write.  The file will be created if it doesn't
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * already exist and "okayToCreate" is set.
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns NULL on failure.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectZipFile* openReadWrite(const char* fileName, bool okayToCreate)
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int flags;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    flags = ZipFile::kOpenReadWrite;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (okayToCreate)
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        flags |= ZipFile::kOpenCreate;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = new ZipFile;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = zip->open(fileName, flags);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result != NO_ERROR) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete zip;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        zip = NULL;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return zip;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a short string describing the compression method.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* compressionName(int method)
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (method == ZipEntry::kCompressStored)
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Stored";
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else if (method == ZipEntry::kCompressDeflated)
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Deflated";
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "Unknown";
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the percent reduction in size (0% == no compression).
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint calcPercent(long uncompressedLen, long compressedLen)
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!uncompressedLen)
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "list" command, which can be a simple file dump or
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a verbose listing.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The verbose listing closely matches the output of the Info-ZIP "unzip"
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * command.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doList(Bundle* bundle)
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result = 1;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ZipEntry* entry;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long totalUncLen, totalCompLen;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() != 1) {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: specify zip file name (only)\n");
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadOnly(zipFileName);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL)
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int count, i;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("Archive:  %s\n", zipFileName);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
146fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
148fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    totalUncLen = totalCompLen = 0;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    count = zip->getNumEntries();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < count; i++) {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = zip->getEntryByIndex(i);
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getVerbose()) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            char dateBuf[32];
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            time_t when;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            when = entry->getModWhen();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                localtime(&when));
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
164fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (long) entry->getUncompressedLen(),
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                compressionName(entry->getCompressionMethod()),
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (long) entry->getCompressedLen(),
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                calcPercent(entry->getUncompressedLen(),
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            entry->getCompressedLen()),
170fb2a9467ad77336edbf2a1a272dbe6ec30ef8a1bKenny Root                (size_t) entry->getLFHOffset(),
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dateBuf,
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                entry->getCRC32(),
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                entry->getFileName());
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("%s\n", entry->getFileName());
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        totalUncLen += entry->getUncompressedLen();
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        totalCompLen += entry->getCompressedLen();
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf(
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "--------          -------  ---                            -------\n");
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("%8ld          %7ld  %2d%%                            %d files\n",
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            totalUncLen,
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            totalCompLen,
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            calcPercent(totalUncLen, totalCompLen),
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            zip->getNumEntries());
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getAndroidList()) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetManager assets;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1987ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const ResTable& res = assets.getResources(false);
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (&res == NULL) {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nNo resource table found.\n");
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
203f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#ifndef HAVE_ANDROID_OS
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nResource table:\n");
205e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            res.print(false);
206f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#endif
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2087ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                   Asset::ACCESS_BUFFER);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (manifestAsset == NULL) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nNo AndroidManifest.xml found.\n");
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nAndroid manifest:\n");
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tree.setTo(manifestAsset->getBuffer(true),
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       manifestAsset->getLength());
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printXMLBlock(&tree);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete manifestAsset;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2227ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = 0;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t N = tree.getAttributeCount();
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tree.getAttributeNameResID(i) == attrRes) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (ssize_t)i;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2411553c82e084ac5763fb393857224145506771b99Joe OnoratoString8 getAttribute(const ResXMLTree& tree, const char* ns,
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            const char* attr, String8* outError)
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = tree.indexOfAttribute(ns, attr);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
278bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackbornstatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
279bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        String8* outError, int32_t defValue = -1)
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
283bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        return defValue;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
287bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        if (value.dataType < Res_value::TYPE_FIRST_INT
288bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                || value.dataType > Res_value::TYPE_LAST_INT) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not an integer value";
290bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            return defValue;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return value.data;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
296f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackbornstatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
297f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        uint32_t attrRes, String8* outError, int32_t defValue = -1)
298f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn{
299f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    ssize_t idx = indexOfAttribute(tree, attrRes);
300f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    if (idx < 0) {
301f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        return defValue;
302f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    }
303f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    Res_value value;
304f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
305f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        if (value.dataType == Res_value::TYPE_REFERENCE) {
306f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            resTable->resolveReference(&value, 0);
307f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        }
308f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        if (value.dataType < Res_value::TYPE_FIRST_INT
309f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                || value.dataType > Res_value::TYPE_LAST_INT) {
310f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            if (outError != NULL) *outError = "attribute is not an integer value";
311f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            return defValue;
312f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        }
313f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    }
314f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    return value.data;
315f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn}
316f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t attrRes, String8* outError)
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType == Res_value::TYPE_STRING) {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return str ? String8(str, len) : String8();
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        resTable->resolveReference(&value, 0);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const Res_value* value2 = &value;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// These are attribute resource constants for the platform, as found
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// in android.R.attr
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum {
346f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    LABEL_ATTR = 0x01010001,
347f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    ICON_ATTR = 0x01010002,
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NAME_ATTR = 0x01010003,
349b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill    DEBUGGABLE_ATTR = 0x0101000f,
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    VERSION_CODE_ATTR = 0x0101021b,
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    VERSION_NAME_ATTR = 0x0101021c,
352f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    SCREEN_ORIENTATION_ATTR = 0x0101001e,
353bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    MIN_SDK_VERSION_ATTR = 0x0101020c,
35475c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu    MAX_SDK_VERSION_ATTR = 0x01010271,
355bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
356bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
357bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
358bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_NAVIGATION_ATTR = 0x0101022a,
359bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
360bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    TARGET_SDK_VERSION_ATTR = 0x01010270,
361bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    TEST_ONLY_ATTR = 0x01010272,
362a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    ANY_DENSITY_ATTR = 0x0101026c,
363e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn    GL_ES_VERSION_ATTR = 0x01010281,
364723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    SMALL_SCREEN_ATTR = 0x01010284,
365723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    NORMAL_SCREEN_ATTR = 0x01010285,
366723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    LARGE_SCREEN_ATTR = 0x01010286,
367f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn    XLARGE_SCREEN_ATTR = 0x010102bf,
368e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn    REQUIRED_ATTR = 0x0101028e,
369a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    SCREEN_SIZE_ATTR = 0x010102ca,
370a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    SCREEN_DENSITY_ATTR = 0x010102cb,
371e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
372e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
373e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
37456088a55ca6c9277f09040a7883117cb127e1e56Kenny Root    PUBLIC_KEY_ATTR = 0x010103a6,
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3777ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapuconst char *getComponentName(String8 &pkgName, String8 &componentName) {
3787ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    ssize_t idx = componentName.find(".");
3797ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    String8 retStr(pkgName);
3807ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    if (idx == 0) {
3817ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += componentName;
3827ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    } else if (idx < 0) {
3837ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += ".";
3847ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += componentName;
3857ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    } else {
3867ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        return componentName.string();
3877ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    }
3887ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    return retStr.string();
3897ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu}
3907ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
391a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackbornstatic void printCompatibleScreens(ResXMLTree& tree) {
392a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    size_t len;
393a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    ResXMLTree::event_code_t code;
394a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    int depth = 0;
395a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    bool first = true;
396a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    printf("compatible-screens:");
397a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
398a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (code == ResXMLTree::END_TAG) {
399a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            depth--;
400a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (depth < 0) {
401a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                break;
402a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
403a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            continue;
404a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
405a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (code != ResXMLTree::START_TAG) {
406a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            continue;
407a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
408a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        depth++;
409a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        String8 tag(tree.getElementName(&len));
410a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (tag == "screen") {
411a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int32_t screenSize = getIntegerAttribute(tree,
412a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    SCREEN_SIZE_ATTR, NULL, -1);
413a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int32_t screenDensity = getIntegerAttribute(tree,
414a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    SCREEN_DENSITY_ATTR, NULL, -1);
415a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (screenSize > 0 && screenDensity > 0) {
416a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                if (!first) {
417a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    printf(",");
418a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                }
419a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                first = false;
420a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                printf("'%d/%d'", screenSize, screenDensity);
421a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
422a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
423a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    }
424a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    printf("\n");
425a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn}
426a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "dump" command, to extract select data from an archive.
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
430e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrillextern char CONSOLE_DATA[2925]; // see EOF
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doDump(Bundle* bundle)
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* asset = NULL;
4357ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no dump option specified\n");
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4407ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no dump file specified\n");
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4457ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* option = bundle->getFileSpecEntry(0);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* filename = bundle->getFileSpecEntry(1);
4487ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetManager assets;
450bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    void* assetsCookie;
451bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4557ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
456e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // Make a dummy config for retrieving resources...  we need to supply
457e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // non-default values for some configs so that we can retrieve resources
458e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // in the app that don't have a default.  The most important of these is
459e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // the API version because key resources like icons will have an implicit
460e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // version if they are using newer config types like density.
461e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    ResTable_config config;
462e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.language[0] = 'e';
463e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.language[1] = 'n';
464e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.country[0] = 'U';
465e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.country[1] = 'S';
466e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.orientation = ResTable_config::ORIENTATION_PORT;
467e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.density = ResTable_config::DENSITY_MEDIUM;
468e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.sdkVersion = 10000; // Very high.
469e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.screenWidthDp = 320;
470e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.screenHeightDp = 480;
471e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.smallestScreenWidthDp = 320;
472e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    assets.setConfiguration(config);
473e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ResTable& res = assets.getResources(false);
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (&res == NULL) {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4797ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcmp("resources", option) == 0) {
481f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#ifndef HAVE_ANDROID_OS
482e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn        res.print(bundle->getValues());
483f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#endif
4846c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn
4856c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn    } else if (strcmp("strings", option) == 0) {
4866c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn        const ResStringPool* pool = res.getTableStringBlock(0);
4876c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn        printStringPool(pool);
4886c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp("xmltree", option) == 0) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getFileSpecCount() < 3) {
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4947ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=2; i<bundle->getFileSpecCount(); i++) {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* resname = bundle->getFileSpecEntry(i);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (asset == NULL) {
50044b283dc27ed8ba5a946d809489f29b4ae88cb15Kenny Root                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5037ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tree.setTo(asset->getBuffer(true),
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           asset->getLength()) != NO_ERROR) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tree.restart();
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printXMLBlock(&tree);
51119138468caf7050d482dc15f35a344eab11bb756Kenny Root            tree.uninit();
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete asset;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = NULL;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5157ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp("xmlstrings", option) == 0) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getFileSpecCount() < 3) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5217ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=2; i<bundle->getFileSpecCount(); i++) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* resname = bundle->getFileSpecEntry(i);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (asset == NULL) {
52744b283dc27ed8ba5a946d809489f29b4ae88cb15Kenny Root                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5307ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tree.setTo(asset->getBuffer(true),
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           asset->getLength()) != NO_ERROR) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printStringPool(&tree.getStrings());
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete asset;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = NULL;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5407ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ResXMLTree tree;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        asset = assets.openNonAsset("AndroidManifest.xml",
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            Asset::ACCESS_BUFFER);
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (asset == NULL) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5497ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tree.setTo(asset->getBuffer(true),
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       asset->getLength()) != NO_ERROR) {
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tree.restart();
5567ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcmp("permissions", option) == 0) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree::event_code_t code;
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int depth = 0;
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code != ResXMLTree::START_TAG) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                depth++;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 tag(tree.getElementName(&len));
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("Depth %d tag %s\n", depth, tag.string());
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (depth == 1) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag != "manifest") {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("package: %s\n", pkg.string());
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 2 && tag == "permission") {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 error;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 name = getAttribute(tree, NAME_ATTR, &error);
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: %s\n", error.string());
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("permission: %s\n", name.string());
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 2 && tag == "uses-permission") {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 error;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 name = getAttribute(tree, NAME_ATTR, &error);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: %s\n", error.string());
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("uses-permission: %s\n", name.string());
5951bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                    int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
5961bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                    if (!req) {
5971bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                        printf("optional-permission: %s\n", name.string());
5981bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                    }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strcmp("badging", option) == 0) {
602e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            Vector<String8> locales;
603e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            res.getLocales(&locales);
604e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
605e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            Vector<ResTable_config> configs;
606e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            res.getConfigurations(&configs);
607e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            SortedVector<int> densities;
608e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            const size_t NC = configs.size();
609e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            for (size_t i=0; i<NC; i++) {
610e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                int dens = configs[i].density;
611e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (dens == 0) dens = 160;
612e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                densities.add(dens);
613e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
614e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree::event_code_t code;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int depth = 0;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 error;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool withinActivity = false;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool isMainActivity = false;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool isLauncherActivity = false;
6221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool isSearchable = false;
6237ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            bool withinApplication = false;
624eaeb19048672337714c1724de7992be8cb3f2124Michael Wright            bool withinSupportsInput = false;
6257ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            bool withinReceiver = false;
6261b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool withinService = false;
6271b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool withinIntentFilter = false;
6281b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasMainActivity = false;
6291b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherActivities = false;
6301b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherReceivers = false;
6311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherServices = false;
6321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasWallpaperService = false;
6331b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasImeService = false;
6341b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasWidgetReceivers = false;
6351b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasIntentFilter = false;
6361b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actMainActivity = false;
6371b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actWidgetReceivers = false;
6381b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actImeService = false;
6391b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actWallpaperService = false;
64089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
641063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // These two implement the implicit permissions that are granted
642063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // to pre-1.6 applications.
643063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            bool hasWriteExternalStoragePermission = false;
644063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            bool hasReadPhoneStatePermission = false;
645063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root
6467924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // If an app requests write storage, they will also get read storage.
6477924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            bool hasReadExternalStoragePermission = false;
6487924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn
64931b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            // Implement transition to read and write call log.
65031b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasReadContactsPermission = false;
65131b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasWriteContactsPermission = false;
65231b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasReadCallLogPermission = false;
65331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasWriteCallLogPermission = false;
65431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn
65589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // This next group of variables is used to implement a group of
65689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // backward-compatibility heuristics necessitated by the addition of
65789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
65889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // heuristic is "if an app requests a permission but doesn't explicitly
65989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // request the corresponding <uses-feature>, presume it's there anyway".
66089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specCameraFeature = false; // camera-related
66189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specCameraAutofocusFeature = false;
66289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqCameraAutofocusFeature = false;
66389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqCameraFlashFeature = false;
664e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn            bool hasCameraPermission = false;
66589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specLocationFeature = false; // location-related
66689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specNetworkLocFeature = false;
66789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqNetworkLocFeature = false;
668ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            bool specGpsFeature = false;
66989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqGpsFeature = false;
67089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasMockLocPermission = false;
67189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasCoarseLocPermission = false;
672ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            bool hasGpsPermission = false;
67389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasGeneralLocPermission = false;
67489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specBluetoothFeature = false; // Bluetooth API-related
67589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasBluetoothPermission = false;
67689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specMicrophoneFeature = false; // microphone-related
67789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasRecordAudioPermission = false;
67889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specWiFiFeature = false;
67989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasWiFiPermission = false;
68089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specTelephonyFeature = false; // telephony-related
68189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqTelephonySubFeature = false;
68289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasTelephonyPermission = false;
68389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specTouchscreenFeature = false; // touchscreen-related
68489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specMultitouchFeature = false;
68589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqDistinctMultitouchFeature = false;
686e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            bool specScreenPortraitFeature = false;
687e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            bool specScreenLandscapeFeature = false;
688f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            bool reqScreenPortraitFeature = false;
689f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            bool reqScreenLandscapeFeature = false;
69089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // 2.2 also added some other features that apps can request, but that
69189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // have no corresponding permission, so we cannot implement any
69289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // back-compatibility heuristic for them. The below are thus unnecessary
69389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // (but are retained here for documentary purposes.)
69489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specCompassFeature = false;
69589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specAccelerometerFeature = false;
69689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specProximityFeature = false;
69789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specAmbientLightFeature = false;
69889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specLiveWallpaperFeature = false;
69989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
700723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int targetSdk = 0;
701723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int smallScreen = 1;
702723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int normalScreen = 1;
703723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int largeScreen = 1;
704f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            int xlargeScreen = 1;
705a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int anyDensity = 1;
706e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int requiresSmallestWidthDp = 0;
707e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int compatibleWidthLimitDp = 0;
708e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int largestWidthLimitDp = 0;
7097ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            String8 pkg;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityName;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityLabel;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityIcon;
7137ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            String8 receiverName;
7141b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            String8 serviceName;
715eaeb19048672337714c1724de7992be8cb3f2124Michael Wright            Vector<String8> supportedInput;
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
7191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (depth < 2) {
720eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
721eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            printf("supports-input: '");
722eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            const size_t N = supportedInput.size();
723eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            for (size_t i=0; i<N; i++) {
724eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                printf("%s", supportedInput[i].string());
725eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                if (i != N - 1) {
726eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    printf("' '");
727eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                } else {
728eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    printf("'\n");
729eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                }
730eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
731eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            supportedInput.clear();
732eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        }
7331b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinApplication = false;
734eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        withinSupportsInput = false;
7351b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (depth < 3) {
7361b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity && isMainActivity && isLauncherActivity) {
7371b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            const char *aName = getComponentName(pkg, activityName);
738e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            printf("launchable-activity:");
7391b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (aName != NULL) {
740e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                printf(" name='%s' ", aName);
7411b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
742e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            printf(" label='%s' icon='%s'\n",
7431b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                    activityLabel.string(),
7441b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                    activityIcon.string());
7451b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
7461b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (!hasIntentFilter) {
7471b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherActivities |= withinActivity;
7481b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherReceivers |= withinReceiver;
7491b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherServices |= withinService;
7501b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
7511b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinActivity = false;
7521b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinService = false;
7531b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinReceiver = false;
7541b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        hasIntentFilter = false;
7551b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        isMainActivity = isLauncherActivity = false;
7561b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (depth < 4) {
7571b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinIntentFilter) {
7581b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (withinActivity) {
7591b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasMainActivity |= actMainActivity;
7601b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherActivities |= !actMainActivity;
7611b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (withinReceiver) {
7621b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasWidgetReceivers |= actWidgetReceivers;
7631b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherReceivers |= !actWidgetReceivers;
7641b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (withinService) {
7651b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasImeService |= actImeService;
7661b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasWallpaperService |= actWallpaperService;
7671b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherServices |= (!actImeService && !actWallpaperService);
7681b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
7691b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
7701b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinIntentFilter = false;
7711b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code != ResXMLTree::START_TAG) {
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                depth++;
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 tag(tree.getElementName(&len));
7791b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                //printf("Depth %d,  %s\n", depth, tag.string());
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (depth == 1) {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag != "manifest") {
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7857ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    pkg = getAttribute(tree, NULL, "package", NULL);
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("package: name='%s' ", pkg.string());
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (versionCode > 0) {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("versionCode='%d' ", versionCode);
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("versionCode='' ");
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
797cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("versionName='%s'\n", versionName.string());
8037ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                } else if (depth == 2) {
8047ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinApplication = false;
8057ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    if (tag == "application") {
8067ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        withinApplication = true;
807e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
808e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        String8 label;
809e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        const size_t NL = locales.size();
810e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        for (size_t i=0; i<NL; i++) {
811e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            const char* localeStr =  locales[i].string();
812e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            assets.setLocale(localeStr != NULL ? localeStr : "");
813e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
814e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            if (llabel != "") {
815e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                if (localeStr == NULL || strlen(localeStr) == 0) {
816e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    label = llabel;
817e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    printf("application-label:'%s'\n", llabel.string());
818e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                } else {
819e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    if (label == "") {
820e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                        label = llabel;
821e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    }
822e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    printf("application-label-%s:'%s'\n", localeStr,
823e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                            llabel.string());
824e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                }
825e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            }
8267ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
827e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
828e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        ResTable_config tmpConfig = config;
829e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        const size_t ND = densities.size();
830e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        for (size_t i=0; i<ND; i++) {
831e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            tmpConfig.density = densities[i];
832e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            assets.setConfiguration(tmpConfig);
833e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
834e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            if (icon != "") {
835e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                printf("application-icon-%d:'%s'\n", densities[i], icon.string());
836e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            }
837e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        }
838e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        assets.setConfiguration(config);
839e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
8407ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
8417ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
8427ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
8437ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
8447ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
845bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
8467ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
847bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
8487ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
8497ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
850e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        printf("application: label='%s' ", label.string());
851e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        printf("icon='%s'\n", icon.string());
852bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (testOnly != 0) {
853bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("testOnly='%d'\n", testOnly);
854bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
855b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill
856b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
857b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        if (error != "") {
858b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
859b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                            goto bail;
860b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        }
861b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        if (debuggable != 0) {
862b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                            printf("application-debuggable\n");
863b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        }
864bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    } else if (tag == "uses-sdk") {
865bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
866bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (error != "") {
867bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            error = "";
868bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
869bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (error != "") {
870bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
871bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                        error.string());
872bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                goto bail;
873bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
874723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (name == "Donut") targetSdk = 4;
875bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("sdkVersion:'%s'\n", name.string());
876bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        } else if (code != -1) {
877723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            targetSdk = code;
878bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("sdkVersion:'%d'\n", code);
879bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
88075c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
88175c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        if (code != -1) {
88275c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                            printf("maxSdkVersion:'%d'\n", code);
88375c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        }
884bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
885bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (error != "") {
886bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            error = "";
887bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
888bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (error != "") {
889bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
890bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                        error.string());
891bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                goto bail;
892bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
893723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
894bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("targetSdkVersion:'%s'\n", name.string());
895bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        } else if (code != -1) {
896723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (targetSdk < code) {
897723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                targetSdk = code;
898723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            }
899bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("targetSdkVersion:'%d'\n", code);
900bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
901bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    } else if (tag == "uses-configuration") {
902bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqTouchScreen = getIntegerAttribute(tree,
903bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
904bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqKeyboardType = getIntegerAttribute(tree,
905bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
906bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
907bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
908bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqNavigation = getIntegerAttribute(tree,
909bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_NAVIGATION_ATTR, NULL, 0);
910bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
911bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
912cb2d50d0d6e2e37ae02b014999da23ecd32038b8Dianne Hackborn                        printf("uses-configuration:");
913bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqTouchScreen != 0) {
914bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqTouchScreen='%d'", reqTouchScreen);
915bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
916bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqKeyboardType != 0) {
917bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqKeyboardType='%d'", reqKeyboardType);
918bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
919bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqHardKeyboard != 0) {
920bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
921bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
922bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqNavigation != 0) {
923bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqNavigation='%d'", reqNavigation);
9247ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
925bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqFiveWayNav != 0) {
926bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
927bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
928bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        printf("\n");
929eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                    } else if (tag == "supports-input") {
930eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        withinSupportsInput = true;
931723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                    } else if (tag == "supports-screens") {
932723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        smallScreen = getIntegerAttribute(tree,
933723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                SMALL_SCREEN_ATTR, NULL, 1);
934723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        normalScreen = getIntegerAttribute(tree,
935723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                NORMAL_SCREEN_ATTR, NULL, 1);
936723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        largeScreen = getIntegerAttribute(tree,
937723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                LARGE_SCREEN_ATTR, NULL, 1);
938f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn                        xlargeScreen = getIntegerAttribute(tree,
939f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn                                XLARGE_SCREEN_ATTR, NULL, 1);
940a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        anyDensity = getIntegerAttribute(tree,
941a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                                ANY_DENSITY_ATTR, NULL, 1);
942e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        requiresSmallestWidthDp = getIntegerAttribute(tree,
943e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
944e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        compatibleWidthLimitDp = getIntegerAttribute(tree,
945e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
946e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        largestWidthLimitDp = getIntegerAttribute(tree,
947e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
948e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                    } else if (tag == "uses-feature") {
949e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
95040b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu
95140b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu                        if (name != "" && error == "") {
952e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            int req = getIntegerAttribute(tree,
953e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    REQUIRED_ATTR, NULL, 1);
95489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
955e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (name == "android.hardware.camera") {
956e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                specCameraFeature = true;
95789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.camera.autofocus") {
95889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
95989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational camera permission
96089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqCameraAutofocusFeature = reqCameraAutofocusFeature || req;
96189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specCameraAutofocusFeature = true;
96289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (req && (name == "android.hardware.camera.flash")) {
96389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
96489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational camera permission
96589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqCameraFlashFeature = true;
96689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.location") {
96789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specLocationFeature = true;
96889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.location.network") {
96989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specNetworkLocFeature = true;
97089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqNetworkLocFeature = reqNetworkLocFeature || req;
971ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                            } else if (name == "android.hardware.location.gps") {
972ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                                specGpsFeature = true;
97389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqGpsFeature = reqGpsFeature || req;
97489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.bluetooth") {
97589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specBluetoothFeature = true;
97689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen") {
97789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specTouchscreenFeature = true;
97889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen.multitouch") {
97989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specMultitouchFeature = true;
98089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
98189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req;
98289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.microphone") {
98389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specMicrophoneFeature = true;
98489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.wifi") {
98589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specWiFiFeature = true;
98689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.telephony") {
98789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specTelephonyFeature = true;
98889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (req && (name == "android.hardware.telephony.gsm" ||
98989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                               name == "android.hardware.telephony.cdma")) {
99089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
99189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational telephony permission
99289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqTelephonySubFeature = true;
993e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            } else if (name == "android.hardware.screen.portrait") {
994e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                specScreenPortraitFeature = true;
995e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            } else if (name == "android.hardware.screen.landscape") {
996e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                specScreenLandscapeFeature = true;
997e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
998e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            printf("uses-feature%s:'%s'\n",
999e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    req ? "" : "-not-required", name.string());
1000e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        } else {
1001e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            int vers = getIntegerAttribute(tree,
1002e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    GL_ES_VERSION_ATTR, &error);
1003e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (error == "") {
1004e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                printf("uses-gl-es:'0x%x'\n", vers);
1005e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
1006e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        }
1007e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                    } else if (tag == "uses-permission") {
1008e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
100940b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu                        if (name != "" && error == "") {
1010e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (name == "android.permission.CAMERA") {
1011e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                hasCameraPermission = true;
1012ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
1013ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                                hasGpsPermission = true;
101489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
101589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasMockLocPermission = true;
101689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
101789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasCoarseLocPermission = true;
101889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
101989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
102089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasGeneralLocPermission = true;
102189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.BLUETOOTH" ||
102289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.BLUETOOTH_ADMIN") {
102389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasBluetoothPermission = true;
102489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.RECORD_AUDIO") {
102589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasRecordAudioPermission = true;
102689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
102789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CHANGE_WIFI_STATE" ||
102889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
102989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasWiFiPermission = true;
103089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.CALL_PHONE" ||
103189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CALL_PRIVILEGED" ||
103289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.MODIFY_PHONE_STATE" ||
103389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
103489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.READ_SMS" ||
103589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_SMS" ||
103689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_MMS" ||
103789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
103889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.SEND_SMS" ||
103989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.WRITE_APN_SETTINGS" ||
104089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.WRITE_SMS") {
104189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasTelephonyPermission = true;
1042063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1043063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                                hasWriteExternalStoragePermission = true;
10447924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
10457924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                                hasReadExternalStoragePermission = true;
1046063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                            } else if (name == "android.permission.READ_PHONE_STATE") {
1047063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                                hasReadPhoneStatePermission = true;
104831b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.READ_CONTACTS") {
104931b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasReadContactsPermission = true;
105031b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.WRITE_CONTACTS") {
105131b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasWriteContactsPermission = true;
105231b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.READ_CALL_LOG") {
105331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasReadCallLogPermission = true;
105431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.WRITE_CALL_LOG") {
105531b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasWriteCallLogPermission = true;
1056e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
1057e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            printf("uses-permission:'%s'\n", name.string());
10581bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                            int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
10591bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                            if (!req) {
10601bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                                printf("optional-permission:'%s'\n", name.string());
10611bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                            }
1062e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        } else {
1063e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1064e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    error.string());
1065e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            goto bail;
1066e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        }
106743b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                    } else if (tag == "uses-package") {
106843b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
106943b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        if (name != "" && error == "") {
107043b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                            printf("uses-package:'%s'\n", name.string());
107143b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        } else {
107243b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
107343b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                                    error.string());
107443b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                                goto bail;
107543b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        }
1076e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                    } else if (tag == "original-package") {
1077e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1078e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        if (name != "" && error == "") {
1079e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                            printf("original-package:'%s'\n", name.string());
1080e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        } else {
1081e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1082e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                                    error.string());
1083e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                                goto bail;
1084e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        }
1085096b67f65510a5076f1f845f9e19dda2b30ea6bbDan Morrill                    } else if (tag == "supports-gl-texture") {
10866f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        String8 name = getAttribute(tree, NAME_ATTR, &error);
10876f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        if (name != "" && error == "") {
1088096b67f65510a5076f1f845f9e19dda2b30ea6bbDan Morrill                            printf("supports-gl-texture:'%s'\n", name.string());
10896f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        } else {
10906f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
10916f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                                    error.string());
10926f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                                goto bail;
10936f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        }
1094a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    } else if (tag == "compatible-screens") {
1095a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        printCompatibleScreens(tree);
1096a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        depth--;
109756088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                    } else if (tag == "package-verifier") {
109856088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        String8 name = getAttribute(tree, NAME_ATTR, &error);
109956088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        if (name != "" && error == "") {
110056088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
110156088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            if (publicKey != "" && error == "") {
110256088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                                printf("package-verifier: name='%s' publicKey='%s'\n",
110356088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                                        name.string(), publicKey.string());
110456088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            }
110556088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        }
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1107eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                } else if (depth == 3) {
11087ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinActivity = false;
11097ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinReceiver = false;
11101b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    withinService = false;
11111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    hasIntentFilter = false;
1112eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                    if (withinApplication) {
1113eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        if(tag == "activity") {
1114eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            withinActivity = true;
1115eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            activityName = getAttribute(tree, NAME_ATTR, &error);
1116eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1117eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1118eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        error.string());
1119eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1120eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1122eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1123eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1124eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1125eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        error.string());
1126eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1127eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1130eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1131eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1132eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        error.string());
1133eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1134eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1135f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn
1136eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            int32_t orien = getResolvedIntegerAttribute(&res, tree,
1137eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1138eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error == "") {
1139eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1140eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
1141eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    reqScreenLandscapeFeature = true;
1142eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1143eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
1144eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    reqScreenPortraitFeature = true;
1145eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                }
1146f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                            }
1147eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else if (tag == "uses-library") {
1148eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
1149eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1150eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr,
1151eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1152eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        " %s\n", error.string());
1153eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1154eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1155eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            int req = getIntegerAttribute(tree,
1156eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    REQUIRED_ATTR, NULL, 1);
1157eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            printf("uses-library%s:'%s'\n",
1158eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    req ? "" : "-not-required", libraryName.string());
1159eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else if (tag == "receiver") {
1160eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            withinReceiver = true;
1161eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            receiverName = getAttribute(tree, NAME_ATTR, &error);
11627ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
1163eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1164eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr,
1165eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1166eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        " %s\n", error.string());
1167eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1168eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1169eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else if (tag == "service") {
1170eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            withinService = true;
1171eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            serviceName = getAttribute(tree, NAME_ATTR, &error);
11721b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1173eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1174eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for"
1175eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        " service: %s\n", error.string());
1176eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1177eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1178eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        }
1179eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                    } else if (withinSupportsInput && tag == "input-type") {
1180eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1181eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        if (name != "" && error == "") {
1182eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            supportedInput.add(name);
1183eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else {
1184eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1185eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    error.string());
11861b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
11871b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
11887ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    }
11891b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                } else if ((depth == 4) && (tag == "intent-filter")) {
11901b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    hasIntentFilter = true;
11911b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    withinIntentFilter = true;
11921b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    actMainActivity = actWidgetReceivers = actImeService = actWallpaperService = false;
11931b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                } else if ((depth == 5) && withinIntentFilter){
11941b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    String8 action;
11951b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (tag == "action") {
11961b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        action = getAttribute(tree, NAME_ATTR, &error);
11971b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
11981b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
11991b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
12001b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
12011b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity) {
1202bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (action == "android.intent.action.MAIN") {
1203bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                isMainActivity = true;
12041b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actMainActivity = true;
1205bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
12061b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        } else if (withinReceiver) {
12071b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
12081b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actWidgetReceivers = true;
12097ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            }
12101b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        } else if (withinService) {
12111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (action == "android.view.InputMethod") {
12121b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actImeService = true;
12131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (action == "android.service.wallpaper.WallpaperService") {
12141b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actWallpaperService = true;
12157ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            }
12167ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
12171b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (action == "android.intent.action.SEARCH") {
12181b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            isSearchable = true;
12197ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (tag == "category") {
12231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        String8 category = getAttribute(tree, NAME_ATTR, &error);
12241b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
12251b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n", error.string());
12261b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
12271b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
12281b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity) {
12291b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (category == "android.intent.category.LAUNCHER") {
12301b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                isLauncherActivity = true;
12311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
12321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
12337ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    }
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1236063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root
1237063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // Pre-1.6 implicitly granted permission compatibility logic
1238063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            if (targetSdk < 4) {
1239063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                if (!hasWriteExternalStoragePermission) {
1240063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                    printf("uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE'\n");
12414aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.WRITE_EXTERNAL_STORAGE'," \
12424aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 4'\n");
12437924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                    hasWriteExternalStoragePermission = true;
1244063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                }
1245063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                if (!hasReadPhoneStatePermission) {
1246063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                    printf("uses-permission:'android.permission.READ_PHONE_STATE'\n");
12474aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.READ_PHONE_STATE'," \
12484aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 4'\n");
1249063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                }
1250063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            }
12511b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
12527924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
12532bd8d0403be62df679f0f94ab4d84c9ae9a2e918Dianne Hackborn            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
12542bd8d0403be62df679f0f94ab4d84c9ae9a2e918Dianne Hackborn            // do this (regardless of target API version) because we can't have
12552bd8d0403be62df679f0f94ab4d84c9ae9a2e918Dianne Hackborn            // an app with write permission but not read permission.
12567924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
12577924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
12584aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-permission:'android.permission.READ_EXTERNAL_STORAGE'," \
12594aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested WRITE_EXTERNAL_STORAGE'\n");
12607924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            }
12617924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn
126231b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            // Pre-JellyBean call log permission compatibility.
126331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            if (targetSdk < 16) {
126431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                if (!hasReadCallLogPermission && hasReadContactsPermission) {
126531b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                    printf("uses-permission:'android.permission.READ_CALL_LOG'\n");
12664aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.READ_CALL_LOG'," \
12674aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 16 and requested READ_CONTACTS'\n");
126831b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                }
126931b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
127031b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                    printf("uses-permission:'android.permission.WRITE_CALL_LOG'\n");
12714aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.WRITE_CALL_LOG'," \
12724aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 16 and requested WRITE_CONTACTS'\n");
127331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                }
127431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            }
127531b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn
127689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            /* The following blocks handle printing "inferred" uses-features, based
127789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * on whether related features or permissions are used by the app.
127889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * Note that the various spec*Feature variables denote whether the
127989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * relevant tag was *present* in the AndroidManfest, not that it was
128089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * present and set to true.
128189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             */
128289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Camera-related back-compatibility logic
128389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specCameraFeature) {
12844aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                if (reqCameraFlashFeature) {
128589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // if app requested a sub-feature (autofocus or flash) and didn't
128689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // request the base camera feature, we infer that it meant to
128789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    printf("uses-feature:'android.hardware.camera'\n");
12884aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.camera'," \
12894aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'requested android.hardware.camera.flash feature'\n");
12904aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                } else if (reqCameraAutofocusFeature) {
12914aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    // if app requested a sub-feature (autofocus or flash) and didn't
12924aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    // request the base camera feature, we infer that it meant to
12934aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-feature:'android.hardware.camera'\n");
12944aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.camera'," \
12954aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'requested android.hardware.camera.autofocus feature'\n");
129689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                } else if (hasCameraPermission) {
129789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // if app wants to use camera but didn't request the feature, we infer
129889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // that it meant to, and further that it wants autofocus
129989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // (which was the 1.0 - 1.5 behavior)
130089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    printf("uses-feature:'android.hardware.camera'\n");
130189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    if (!specCameraAutofocusFeature) {
130289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                        printf("uses-feature:'android.hardware.camera.autofocus'\n");
13034aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        printf("uses-implied-feature:'android.hardware.camera.autofocus'," \
13044aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                                "'requested android.permission.CAMERA permission'\n");
130589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    }
130689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                }
1307e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn            }
1308dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker
130989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Location-related back-compatibility logic
131089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specLocationFeature &&
131189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission ||
131289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                 hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) {
131389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app either takes a location-related permission or requests one of the
131489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // sub-features, we infer that it also meant to request the base location feature
131589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.location'\n");
13164aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.location'," \
13174aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested a location access permission'\n");
131889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
1319ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            if (!specGpsFeature && hasGpsPermission) {
132089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes GPS (FINE location) perm but does not request the GPS
132189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
1322ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                printf("uses-feature:'android.hardware.location.gps'\n");
13234aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.location.gps'," \
13244aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.ACCESS_FINE_LOCATION permission'\n");
1325ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            }
132689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specNetworkLocFeature && hasCoarseLocPermission) {
132789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes Network location (COARSE location) perm but does not request the
132889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // network location feature, we infer that it meant to
132989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.location.network'\n");
13304aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.location.network'," \
1331ec559ff78caa16cffcc7b9d688fe911e8945e17dDianne Hackborn                        "'requested android.permission.ACCESS_COARSE_LOCATION permission'\n");
133289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
133389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
133489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Bluetooth-related compatibility logic
13356b22d81aa35d9a9b32670995c002e92588b2fe09Dan Morrill            if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) {
133689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes a Bluetooth permission but does not request the Bluetooth
133789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
133889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.bluetooth'\n");
13394aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.bluetooth'," \
13404aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \
13414aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "permission and targetSdkVersion > 4'\n");
134289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
134389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
134489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Microphone-related compatibility logic
134589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specMicrophoneFeature && hasRecordAudioPermission) {
134689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes the record-audio permission but does not request the microphone
134789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
134889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.microphone'\n");
13494aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.microphone'," \
13504aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.RECORD_AUDIO permission'\n");
135189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
135289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
135389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // WiFi-related compatibility logic
135489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specWiFiFeature && hasWiFiPermission) {
135589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the WiFi permissions but does not request the WiFi
135689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
135789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.wifi'\n");
13584aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.wifi'," \
13594aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.ACCESS_WIFI_STATE, " \
13604aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "android.permission.CHANGE_WIFI_STATE, or " \
13614aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n");
136289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
136389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
136489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Telephony-related compatibility logic
136589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) {
136689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the telephony permissions or requests a sub-feature but
136789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // does not request the base telephony feature, we infer that it meant to
136889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.telephony'\n");
13694aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.telephony'," \
13704aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested a telephony-related permission or feature'\n");
137189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
137289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
137389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Touchscreen-related back-compatibility logic
137489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specTouchscreenFeature) { // not a typo!
137589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // all apps are presumed to require a touchscreen, unless they explicitly say
137689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
137789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // Note that specTouchscreenFeature is true if the tag is present, regardless
137889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // of whether its value is true or false, so this is safe
137989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.touchscreen'\n");
13804aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.touchscreen'," \
13814aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'assumed you require a touch screen unless explicitly made optional'\n");
138289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
138389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specMultitouchFeature && reqDistinctMultitouchFeature) {
138489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the telephony permissions or requests a sub-feature but
138589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // does not request the base telephony feature, we infer that it meant to
138689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
13874aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \
13884aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.hardware.touchscreen.multitouch.distinct feature'\n");
138989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
1390ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn
1391e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // Landscape/portrait-related compatibility logic
1392f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
1393f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // If the app has specified any activities in its manifest
1394f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // that request a specific orientation, then assume that
1395f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // orientation is required.
1396f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                if (reqScreenLandscapeFeature) {
1397f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                    printf("uses-feature:'android.hardware.screen.landscape'\n");
13984aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.screen.landscape'," \
13994aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'one or more activities have specified a landscape orientation'\n");
1400f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                }
1401f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                if (reqScreenPortraitFeature) {
1402f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                    printf("uses-feature:'android.hardware.screen.portrait'\n");
14034aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.screen.portrait'," \
14044aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'one or more activities have specified a portrait orientation'\n");
1405f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                }
1406e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1407e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
14081b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasMainActivity) {
14091b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("main\n");
14101b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasWidgetReceivers) {
14121b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("app-widget\n");
14131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14141b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasImeService) {
14151b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("ime\n");
14161b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14171b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasWallpaperService) {
14181b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("wallpaper\n");
14191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14201b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherActivities) {
14211b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-activities\n");
14221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (isSearchable) {
14241b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("search\n");
14251b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14261b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherReceivers) {
14271b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-receivers\n");
14281b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14291b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherServices) {
14301b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-services\n");
14311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
14321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1433e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // For modern apps, if screen size buckets haven't been specified
1434e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // but the new width ranges have, then infer the buckets from them.
1435e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1436e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    && requiresSmallestWidthDp > 0) {
1437e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                int compatWidth = compatibleWidthLimitDp;
1438e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (compatWidth <= 0) compatWidth = requiresSmallestWidthDp;
1439e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1440e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    smallScreen = -1;
1441e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1442e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    smallScreen = 0;
1443e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1444e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1445e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    normalScreen = -1;
1446e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1447e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    normalScreen = 0;
1448e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1449e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1450e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    largeScreen = -1;
1451e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1452e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    largeScreen = 0;
1453e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1454e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1455e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    xlargeScreen = -1;
1456e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1457e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    xlargeScreen = 0;
1458e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1459e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1460e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
1461723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // Determine default values for any unspecified screen sizes,
1462723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // based on the target SDK of the package.  As of 4 (donut)
1463723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // the screen size support was introduced, so all default to
1464723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // enabled.
1465723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (smallScreen > 0) {
1466723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                smallScreen = targetSdk >= 4 ? -1 : 0;
1467723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1468723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (normalScreen > 0) {
1469723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                normalScreen = -1;
1470723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1471723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (largeScreen > 0) {
1472723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                largeScreen = targetSdk >= 4 ? -1 : 0;
1473723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1474f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            if (xlargeScreen > 0) {
1475d58fb97ddf052b3ceac921ac7e936af990392b2cScott Main                // Introduced in Gingerbread.
1476d58fb97ddf052b3ceac921ac7e936af990392b2cScott Main                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1477f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            }
1478a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (anyDensity > 0) {
1479e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1480e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1481a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
1482723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            printf("supports-screens:");
1483723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (smallScreen != 0) printf(" 'small'");
1484723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (normalScreen != 0) printf(" 'normal'");
1485723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (largeScreen != 0) printf(" 'large'");
1486f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            if (xlargeScreen != 0) printf(" 'xlarge'");
1487723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            printf("\n");
1488a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1489e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (requiresSmallestWidthDp > 0) {
1490e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1491e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1492e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (compatibleWidthLimitDp > 0) {
1493e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1494e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1495e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (largestWidthLimitDp > 0) {
1496e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1497e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1498a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("locales:");
1500e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            const size_t NL = locales.size();
1501e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            for (size_t i=0; i<NL; i++) {
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char* localeStr =  locales[i].string();
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (localeStr == NULL || strlen(localeStr) == 0) {
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    localeStr = "--_--";
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf(" '%s'", localeStr);
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\n");
15091b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1510e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            printf("densities:");
1511e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            const size_t ND = densities.size();
1512e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            for (size_t i=0; i<ND; i++) {
1513e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn                printf(" '%d'", densities[i]);
1514e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            }
1515e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            printf("\n");
15161b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1517bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
1518bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            if (dir != NULL) {
1519bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                if (dir->getFileCount() > 0) {
1520bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    printf("native-code:");
1521bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    for (size_t i=0; i<dir->getFileCount(); i++) {
1522bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        printf(" '%s'", dir->getFileName(i).string());
1523bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    }
1524bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    printf("\n");
1525bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                }
1526bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                delete dir;
1527bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            }
1528e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill        } else if (strcmp("badger", option) == 0) {
15296c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn            printf("%s", CONSOLE_DATA);
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strcmp("configurations", option) == 0) {
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Vector<ResTable_config> configs;
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            res.getConfigurations(&configs);
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const size_t N = configs.size();
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t i=0; i<N; i++) {
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s\n", configs[i].toString().string());
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = NO_ERROR;
15447ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (asset) {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete asset;
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "add" command, which wants to add files to a new or
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pre-existing archive.
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doAdd(Bundle* bundle)
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getUpdate()) {
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* avoid confusion */
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: can't use '-u' with add\n");
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: must specify zip file name\n");
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "NOTE: nothing to do\n");
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadWrite(zipFileName, true);
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fileName = bundle->getFileSpecEntry(i);
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf(" '%s'... (from gzip)\n", fileName);
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1593dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            if (bundle->getJunkPath()) {
1594dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                String8 storageName = String8(fileName).getPathLeaf();
1595dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                printf(" '%s' as '%s'...\n", fileName, storageName.string());
1596dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                result = zip->add(fileName, storageName.string(),
1597dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                                  bundle->getCompressionMethod(), NULL);
1598dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            } else {
1599dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                printf(" '%s'...\n", fileName);
1600dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
1601dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            }
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result != NO_ERROR) {
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (result == NAME_NOT_FOUND)
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, ": file not found\n");
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (result == ALREADY_EXISTS)
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, ": already exists in archive\n");
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "\n");
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = NO_ERROR;
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete files from an existing archive.
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doRemove(Bundle* bundle)
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: must specify zip file name\n");
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "NOTE: nothing to do\n");
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadWrite(zipFileName, false);
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            zipFileName);
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fileName = bundle->getFileSpecEntry(i);
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipEntry* entry;
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = zip->getEntryByName(fileName);
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry == NULL) {
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf(" '%s' NOT FOUND\n", fileName);
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = zip->remove(entry);
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result != NO_ERROR) {
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bundle->getFileSpecEntry(i), zipFileName);
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* update the archive */
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip->flush();
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package up an asset directory and associated application files.
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doPackage(Bundle* bundle)
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* outputAPKFile;
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int retVal = 1;
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err;
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptAssets> assets;
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N;
16889bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    FILE* fp;
16899bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    String8 dependencyFile;
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // -c zz_ZZ means do pseudolocalization
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResourceFilter filter;
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = filter.parse(bundle->getConfigurations());
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err != NO_ERROR) {
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (filter.containsPseudo()) {
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bundle->setPseudolocalize(true);
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    N = bundle->getFileSpecCount();
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDir() == NULL) {
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no input files\n");
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    outputAPKFile = bundle->getOutputAPKFile();
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Make sure the filenames provided exist and are of the appropriate type.
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outputAPKFile) {
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileType type;
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        type = getFileType(outputAPKFile);
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "ERROR: output file '%s' exists but is not regular file\n",
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outputAPKFile);
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Load the assets.
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assets = new AaptAssets();
17249bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
172503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    // Set up the resource gathering in assets if we're going to generate
1726b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // dependency files. Every time we encounter a resource while slurping
1727b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the tree, we'll add it to these stores so we have full resource paths
1728b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // to write to a dependency file.
17299bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    if (bundle->getGenDependencies()) {
173003589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        sp<FilePathStore> resPathStore = new FilePathStore;
173103589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        assets->setFullResPaths(resPathStore);
173203589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        sp<FilePathStore> assetPathStore = new FilePathStore;
173303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        assets->setFullAssetPaths(assetPathStore);
17349bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    }
17359bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = assets->slurpFromArgs(bundle);
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err < 0) {
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1742e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn        assets->print(String8());
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17459bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    // If they asked for any fileAs that need to be compiled, do so.
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = buildResources(bundle, assets);
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != 0) {
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // At this point we've read everything and processed everything.  From here
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // on out it's just writing output files.
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17591644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    // Update symbols with information about which ones are needed as Java symbols.
17601644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    assets->applyJavaSymbols();
17611644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    if (SourcePos::hasErrors()) {
17621644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn        goto bail;
17631644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    }
17641644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn
1765b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // If we've been asked to generate a dependency file, do that here
17669bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    if (bundle->getGenDependencies()) {
1767b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // If this is the packaging step, generate the dependency file next to
1768b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // the output apk (e.g. bin/resources.ap_.d)
176903589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        if (outputAPKFile) {
177003589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile = String8(outputAPKFile);
1771b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Add the .d extension to the dependency file.
177203589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile.append(".d");
177303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        } else {
1774b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Else if this is the R.java dependency generation step,
1775b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // generate the dependency file in the R.java package subdirectory
1776b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/R.java.d
177703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile = String8(bundle->getRClassDir());
1778b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            dependencyFile.appendPath("R.java.d");
177903589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        }
17809bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        // Make sure we have a clean dependency file to start with
17819bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        fp = fopen(dependencyFile, "w");
17829bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        fclose(fp);
17839bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    }
17849bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Write out R.java constants
17861644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    if (!assets->havePrivateSymbols()) {
178763459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        if (bundle->getCustomPackage() == NULL) {
1788b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Write the R.java file into the appropriate class directory
1789b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/R.java
179063459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
179163459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        } else {
179263459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            const String8 customPkg(bundle->getCustomPackage());
179363459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            err = writeResourceSymbols(bundle, assets, customPkg, true);
179463459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        }
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1798002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        // If we have library files, we're going to write our R.java file into
1799002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        // the appropriate class directory for those libraries as well.
1800002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        // e.g. gen/com/foo/app/lib/R.java
1801002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        if (bundle->getExtraPackages() != NULL) {
1802002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            // Split on colon
1803002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            String8 libs(bundle->getExtraPackages());
1804002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
1805002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            while (packageString != NULL) {
1806002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                // Write the R.java file out with the correct package name
1807002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                err = writeResourceSymbols(bundle, assets, String8(packageString), true);
1808002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                if (err < 0) {
1809002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                    goto bail;
1810002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                }
1811002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                packageString = strtok(NULL, ":");
1812002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            }
1813002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            libs.unlockBuffer();
1814002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        }
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18261553c82e084ac5763fb393857224145506771b99Joe Onorato    // Write out the ProGuard file
18271553c82e084ac5763fb393857224145506771b99Joe Onorato    err = writeProguardFile(bundle, assets);
18281553c82e084ac5763fb393857224145506771b99Joe Onorato    if (err < 0) {
18291553c82e084ac5763fb393857224145506771b99Joe Onorato        goto bail;
18301553c82e084ac5763fb393857224145506771b99Joe Onorato    }
18311553c82e084ac5763fb393857224145506771b99Joe Onorato
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Write the apk
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outputAPKFile) {
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeAPK(bundle, assets, String8(outputAPKFile));
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != NO_ERROR) {
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputAPKFile);
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1841b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // If we've been asked to generate a dependency file, we need to finish up here.
1842b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the writeResourceSymbols and writeAPK functions have already written the target
1843b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // half of the dependency file, now we need to write the prerequisites. (files that
1844b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the R.java file or .ap_ file depend on)
184503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    if (bundle->getGenDependencies()) {
184603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        // Now that writeResourceSymbols or writeAPK has taken care of writing
184703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        // the targets to our dependency file, we'll write the prereqs
184803589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fp = fopen(dependencyFile, "a+");
184903589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fprintf(fp, " : ");
185003589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        bool includeRaw = (outputAPKFile != NULL);
185103589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
1852b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // Also manually add the AndroidManifeset since it's not under res/ or assets/
1853b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // and therefore was not added to our pathstores during slurping
185403589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
185503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fclose(fp);
185603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    }
185703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    retVal = 0;
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos::printErrors(stderr);
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return retVal;
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18658a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
18668a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin/*
18678a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * Do PNG Crunching
18688a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * PRECONDITIONS
18698a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  -S flag points to a source directory containing drawable* folders
18708a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  -C flag points to destination directory. The folder structure in the
18718a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *     source directory will be mirrored to the destination (cache) directory
18728a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *
18738a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * POSTCONDITIONS
18748a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  Destination directory will be updated to match the PNG files in
18758a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  the source directory.
18768a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin */
18778a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinint doCrunch(Bundle* bundle)
18788a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
18798a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "Crunching PNG Files in ");
18808a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
18818a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
18828a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
18838a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    updatePreProcessedCache(bundle);
18848a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
18858a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return NO_ERROR;
18868a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
1887e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill
1888b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet/*
1889b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet * Do PNG Crunching on a single flag
1890b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet *  -i points to a single png file
1891b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet *  -o points to a single png output file
1892b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet */
1893b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohetint doSingleCrunch(Bundle* bundle)
1894b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet{
1895b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
1896b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
1897b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet
1898b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    String8 input(bundle->getSingleCrunchInputFile());
1899b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    String8 output(bundle->getSingleCrunchOutputFile());
1900b7de2194d54eb81b1db4b50c171ddd0339831155Xavier Ducrohet
1901c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
1902c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet        // we can't return the status_t as it gets truncate to the lower 8 bits.
1903c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet        return 42;
1904c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet    }
1905b7de2194d54eb81b1db4b50c171ddd0339831155Xavier Ducrohet
1906c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet    return NO_ERROR;
1907b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet}
1908b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet
1909e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrillchar CONSOLE_DATA[2925] = {
1910e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1911e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1912e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1913e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
1914e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
1915e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
1916e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1917e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1918e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
1919e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
1920e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
1921e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1922e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
1923e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1924e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1925e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
1926e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
1927e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1928e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1929e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
1930e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
1931e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
1932e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
1933e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
1934e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1935e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1936e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
1937e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
1938e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
1939e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1940e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
1941e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1942e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1943e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
1944e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
1945e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1946e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1947e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
1948e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
1949e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
1950e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1951e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
1952e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1953e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1954e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
1955e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
1956e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
1957e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
1958e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
1959e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1960e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
1961e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
1962e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
1963e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1964e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
1965e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
1966e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
1967e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
1968e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
1969e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
1970e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
1971e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
1972e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
1973e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
1974e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
1975e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
1976e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
1977e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
1978e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
1979e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
1980e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
1981e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
1982e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1983e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
1984e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
1985e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
1986e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1987e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
1988e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
1989e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
1990e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
1991e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
1992e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
1993e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1994e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
1995e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
1996e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
1997e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
1998e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
1999e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2000e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2001e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2002e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2003e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2004e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2005e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2006e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2007e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2008e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2009e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2010e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2011e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2012e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2013e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2014e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2015e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2016e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2017e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2018e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2019e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2020e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2021e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2022e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2023e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2024e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2025e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2026e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2027e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2028e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2029e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2030e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2031e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2032e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2033e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2034e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2035e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2036e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2037e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2038e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2039e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2040e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2041e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2042e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2043e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2044e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2045e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2046e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2047e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2048e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2049e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2050e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2051e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2052e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2053e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2054e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2055e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2056e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2057e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2058e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2059e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2060e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2061e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2062e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2063e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2064e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2065e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2066e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2067e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2068e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2069e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2070e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2071e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2072e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2073e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill  };
2074