Command.cpp revision b8dc7bc582ee4acd9d6c1379701a002c5ddbe323
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
199b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe#ifdef HAVE_ANDROID_OS
200b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        static const bool kHaveAndroidOs = true;
201b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe#else
202b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        static const bool kHaveAndroidOs = false;
203f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#endif
204b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        const ResTable& res = assets.getResources(false);
205b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        if (!kHaveAndroidOs) {
206b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe            printf("\nResource table:\n");
207b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe            res.print(false);
208b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe        }
2097ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                   Asset::ACCESS_BUFFER);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (manifestAsset == NULL) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nNo AndroidManifest.xml found.\n");
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\nAndroid manifest:\n");
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tree.setTo(manifestAsset->getBuffer(true),
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       manifestAsset->getLength());
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printXMLBlock(&tree);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete manifestAsset;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2237ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = 0;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t N = tree.getAttributeCount();
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (size_t i=0; i<N; i++) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tree.getAttributeNameResID(i) == attrRes) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (ssize_t)i;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2421553c82e084ac5763fb393857224145506771b99Joe OnoratoString8 getAttribute(const ResXMLTree& tree, const char* ns,
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            const char* attr, String8* outError)
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = tree.indexOfAttribute(ns, attr);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
257f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert    const char16_t* str = tree.getAttributeStringValue(idx, &len);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
275f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert    const char16_t* str = tree.getAttributeStringValue(idx, &len);
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackbornstatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
280bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        String8* outError, int32_t defValue = -1)
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
284bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        return defValue;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
288bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn        if (value.dataType < Res_value::TYPE_FIRST_INT
289bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                || value.dataType > Res_value::TYPE_LAST_INT) {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not an integer value";
291bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            return defValue;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return value.data;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
297f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackbornstatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
298f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        uint32_t attrRes, String8* outError, int32_t defValue = -1)
299f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn{
300f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    ssize_t idx = indexOfAttribute(tree, attrRes);
301f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    if (idx < 0) {
302f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        return defValue;
303f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    }
304f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    Res_value value;
305f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
306f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        if (value.dataType == Res_value::TYPE_REFERENCE) {
307f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            resTable->resolveReference(&value, 0);
308f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        }
309f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        if (value.dataType < Res_value::TYPE_FIRST_INT
310f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                || value.dataType > Res_value::TYPE_LAST_INT) {
311f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            if (outError != NULL) *outError = "attribute is not an integer value";
312f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            return defValue;
313f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn        }
314f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    }
315f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    return value.data;
316f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn}
317f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t attrRes, String8* outError)
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t idx = indexOfAttribute(tree, attrRes);
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (idx < 0) {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Res_value value;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType == Res_value::TYPE_STRING) {
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
329f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert            const char16_t* str = tree.getAttributeStringValue(idx, &len);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return str ? String8(str, len) : String8();
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        resTable->resolveReference(&value, 0);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (value.dataType != Res_value::TYPE_STRING) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outError != NULL) *outError = "attribute is not a string value";
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String8();
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const Res_value* value2 = &value;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str ? String8(str, len) : String8();
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// These are attribute resource constants for the platform, as found
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// in android.R.attr
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum {
347f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    LABEL_ATTR = 0x01010001,
348f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    ICON_ATTR = 0x01010002,
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NAME_ATTR = 0x01010003,
350b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski    PERMISSION_ATTR = 0x01010006,
351d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    RESOURCE_ATTR = 0x01010025,
352b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill    DEBUGGABLE_ATTR = 0x0101000f,
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    VERSION_CODE_ATTR = 0x0101021b,
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    VERSION_NAME_ATTR = 0x0101021c,
355f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn    SCREEN_ORIENTATION_ATTR = 0x0101001e,
356bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    MIN_SDK_VERSION_ATTR = 0x0101020c,
35775c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu    MAX_SDK_VERSION_ATTR = 0x01010271,
358bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_TOUCH_SCREEN_ATTR = 0x01010227,
359bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
360bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_HARD_KEYBOARD_ATTR = 0x01010229,
361bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_NAVIGATION_ATTR = 0x0101022a,
362bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
363bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    TARGET_SDK_VERSION_ATTR = 0x01010270,
364bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    TEST_ONLY_ATTR = 0x01010272,
365a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    ANY_DENSITY_ATTR = 0x0101026c,
366e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn    GL_ES_VERSION_ATTR = 0x01010281,
367723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    SMALL_SCREEN_ATTR = 0x01010284,
368723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    NORMAL_SCREEN_ATTR = 0x01010285,
369723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn    LARGE_SCREEN_ATTR = 0x01010286,
370f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn    XLARGE_SCREEN_ATTR = 0x010102bf,
371e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn    REQUIRED_ATTR = 0x0101028e,
372a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    SCREEN_SIZE_ATTR = 0x010102ca,
373a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    SCREEN_DENSITY_ATTR = 0x010102cb,
374e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
375e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
376e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
37756088a55ca6c9277f09040a7883117cb127e1e56Kenny Root    PUBLIC_KEY_ATTR = 0x010103a6,
378d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    CATEGORY_ATTR = 0x010103e8,
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3817ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapuconst char *getComponentName(String8 &pkgName, String8 &componentName) {
3827ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    ssize_t idx = componentName.find(".");
3837ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    String8 retStr(pkgName);
3847ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    if (idx == 0) {
3857ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += componentName;
3867ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    } else if (idx < 0) {
3877ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += ".";
3887ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        retStr += componentName;
3897ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    } else {
3907ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu        return componentName.string();
3917ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    }
3927ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu    return retStr.string();
3937ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu}
3947ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
395a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackbornstatic void printCompatibleScreens(ResXMLTree& tree) {
396a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    size_t len;
397a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    ResXMLTree::event_code_t code;
398a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    int depth = 0;
399a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    bool first = true;
400a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    printf("compatible-screens:");
401a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
402a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (code == ResXMLTree::END_TAG) {
403a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            depth--;
404a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (depth < 0) {
405a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                break;
406a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
407a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            continue;
408a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
409a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (code != ResXMLTree::START_TAG) {
410a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            continue;
411a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
412a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        depth++;
413a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        String8 tag(tree.getElementName(&len));
414a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        if (tag == "screen") {
415a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int32_t screenSize = getIntegerAttribute(tree,
416a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    SCREEN_SIZE_ATTR, NULL, -1);
417a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int32_t screenDensity = getIntegerAttribute(tree,
418a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    SCREEN_DENSITY_ATTR, NULL, -1);
419a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (screenSize > 0 && screenDensity > 0) {
420a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                if (!first) {
421a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    printf(",");
422a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                }
423a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                first = false;
424a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                printf("'%d/%d'", screenSize, screenDensity);
425a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
426a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn        }
427a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    }
428a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn    printf("\n");
429a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn}
430a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn
431d831e80a2fa80d18867e70927e4e8cd797ead56fAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
432d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski        String8 *outError = NULL)
433d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski{
434d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
435d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    if (aidAsset == NULL) {
436d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski        if (outError != NULL) *outError = "xml resource does not exist";
437d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski        return Vector<String8>();
438d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    }
439d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
440d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
441d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
442d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    bool withinApduService = false;
443d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    Vector<String8> categories;
444d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
445d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    String8 error;
446d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    ResXMLTree tree;
447d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
448d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
449d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    size_t len;
450d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    int depth = 0;
451d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    ResXMLTree::event_code_t code;
452d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
453d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski        if (code == ResXMLTree::END_TAG) {
454d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            depth--;
455d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            String8 tag(tree.getElementName(&len));
456d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
457d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            if (depth == 0 && tag == serviceTagName) {
458d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                withinApduService = false;
459d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            }
460d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
461d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski        } else if (code == ResXMLTree::START_TAG) {
462d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            depth++;
463d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            String8 tag(tree.getElementName(&len));
464d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
465d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            if (depth == 1) {
466d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                if (tag == serviceTagName) {
467d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    withinApduService = true;
468d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                }
469d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            } else if (depth == 2 && withinApduService) {
470d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                if (tag == "aid-group") {
471d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
472d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    if (error != "") {
473d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        if (outError != NULL) *outError = error;
474d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        return Vector<String8>();
475d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    }
476d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
477d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    categories.add(category);
478d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                }
479d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            }
480d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski        }
481d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    }
482d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    aidAsset->close();
483d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski    return categories;
484d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski}
485d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "dump" command, to extract select data from an archive.
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
489e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrillextern char CONSOLE_DATA[2925]; // see EOF
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doDump(Bundle* bundle)
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* asset = NULL;
4947ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no dump option specified\n");
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4997ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no dump file specified\n");
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5047ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* option = bundle->getFileSpecEntry(0);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* filename = bundle->getFileSpecEntry(1);
5077ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetManager assets;
509745d4efc8369d255341d810790132660e33d3b61Narayan Kamath    int32_t assetsCookie;
510bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn    if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5147ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
515e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // Make a dummy config for retrieving resources...  we need to supply
516e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // non-default values for some configs so that we can retrieve resources
517e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // in the app that don't have a default.  The most important of these is
518e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // the API version because key resources like icons will have an implicit
519e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    // version if they are using newer config types like density.
520e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    ResTable_config config;
521788fa41482b9d398591b7db8b0b01839029611adNarayan Kamath    memset(&config, 0, sizeof(ResTable_config));
522e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.language[0] = 'e';
523e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.language[1] = 'n';
524e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.country[0] = 'U';
525e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.country[1] = 'S';
526e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.orientation = ResTable_config::ORIENTATION_PORT;
527e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.density = ResTable_config::DENSITY_MEDIUM;
528e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.sdkVersion = 10000; // Very high.
529e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.screenWidthDp = 320;
530e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.screenHeightDp = 480;
531e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    config.smallestScreenWidthDp = 320;
532e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn    assets.setConfiguration(config);
533e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const ResTable& res = assets.getResources(false);
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcmp("resources", option) == 0) {
536f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#ifndef HAVE_ANDROID_OS
537e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn        res.print(bundle->getValues());
538f1ff21ac62a51f5ba8ca0821ea8a90f70957e25dSteve Block#endif
5396c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn
5406c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn    } else if (strcmp("strings", option) == 0) {
5416c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn        const ResStringPool* pool = res.getTableStringBlock(0);
5426c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn        printStringPool(pool);
5436c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp("xmltree", option) == 0) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getFileSpecCount() < 3) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5497ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=2; i<bundle->getFileSpecCount(); i++) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* resname = bundle->getFileSpecEntry(i);
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (asset == NULL) {
55544b283dc27ed8ba5a946d809489f29b4ae88cb15Kenny Root                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5587ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tree.setTo(asset->getBuffer(true),
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           asset->getLength()) != NO_ERROR) {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tree.restart();
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printXMLBlock(&tree);
56619138468caf7050d482dc15f35a344eab11bb756Kenny Root            tree.uninit();
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete asset;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = NULL;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5707ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp("xmlstrings", option) == 0) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getFileSpecCount() < 3) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5767ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=2; i<bundle->getFileSpecCount(); i++) {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char* resname = bundle->getFileSpecEntry(i);
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree tree;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (asset == NULL) {
58244b283dc27ed8ba5a946d809489f29b4ae88cb15Kenny Root                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5857ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (tree.setTo(asset->getBuffer(true),
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           asset->getLength()) != NO_ERROR) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto bail;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printStringPool(&tree.getStrings());
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            delete asset;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asset = NULL;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5957ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ResXMLTree tree;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        asset = assets.openNonAsset("AndroidManifest.xml",
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            Asset::ACCESS_BUFFER);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (asset == NULL) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6047ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tree.setTo(asset->getBuffer(true),
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       asset->getLength()) != NO_ERROR) {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tree.restart();
6117ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcmp("permissions", option) == 0) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree::event_code_t code;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int depth = 0;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code != ResXMLTree::START_TAG) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                depth++;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 tag(tree.getElementName(&len));
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //printf("Depth %d tag %s\n", depth, tag.string());
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (depth == 1) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag != "manifest") {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("package: %s\n", pkg.string());
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 2 && tag == "permission") {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 error;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 name = getAttribute(tree, NAME_ATTR, &error);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: %s\n", error.string());
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("permission: %s\n", name.string());
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (depth == 2 && tag == "uses-permission") {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 error;
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8 name = getAttribute(tree, NAME_ATTR, &error);
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: %s\n", error.string());
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("uses-permission: %s\n", name.string());
6501bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                    int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
6511bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                    if (!req) {
6521bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                        printf("optional-permission: %s\n", name.string());
6531bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                    }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strcmp("badging", option) == 0) {
657e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            Vector<String8> locales;
658e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            res.getLocales(&locales);
659e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
660e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            Vector<ResTable_config> configs;
661e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            res.getConfigurations(&configs);
662e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            SortedVector<int> densities;
663e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            const size_t NC = configs.size();
664e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            for (size_t i=0; i<NC; i++) {
665e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                int dens = configs[i].density;
666e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (dens == 0) dens = 160;
667e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                densities.add(dens);
668e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
669e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t len;
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResXMLTree::event_code_t code;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int depth = 0;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 error;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool withinActivity = false;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool isMainActivity = false;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bool isLauncherActivity = false;
6771b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool isSearchable = false;
6787ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            bool withinApplication = false;
679eaeb19048672337714c1724de7992be8cb3f2124Michael Wright            bool withinSupportsInput = false;
6807ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            bool withinReceiver = false;
6811b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool withinService = false;
6821b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool withinIntentFilter = false;
6831b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasMainActivity = false;
6841b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherActivities = false;
6851b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherReceivers = false;
6861b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasOtherServices = false;
6871b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasWallpaperService = false;
6881b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasImeService = false;
689b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasAccessibilityService = false;
690b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasPrintService = false;
6911b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasWidgetReceivers = false;
692b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasDeviceAdminReceiver = false;
6931b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool hasIntentFilter = false;
694d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            bool hasPaymentService = false;
6951b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actMainActivity = false;
6961b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actWidgetReceivers = false;
697b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool actDeviceAdminEnabled = false;
6981b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actImeService = false;
6991b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            bool actWallpaperService = false;
700b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool actAccessibilityService = false;
701b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool actPrintService = false;
702d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            bool actHostApduService = false;
703d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            bool actOffHostApduService = false;
704d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            bool hasMetaHostPaymentCategory = false;
705d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            bool hasMetaOffHostPaymentCategory = false;
706b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski
707b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            // These permissions are required by services implementing services
708b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            // the system binds to (IME, Accessibility, PrintServices, etc.)
709b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasBindDeviceAdminPermission = false;
710b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasBindInputMethodPermission = false;
711b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasBindAccessibilityServicePermission = false;
712b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            bool hasBindPrintServicePermission = false;
713d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            bool hasBindNfcServicePermission = false;
71489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
715063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // These two implement the implicit permissions that are granted
716063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // to pre-1.6 applications.
717063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            bool hasWriteExternalStoragePermission = false;
718063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            bool hasReadPhoneStatePermission = false;
719063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root
7207924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // If an app requests write storage, they will also get read storage.
7217924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            bool hasReadExternalStoragePermission = false;
7227924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn
72331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            // Implement transition to read and write call log.
72431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasReadContactsPermission = false;
72531b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasWriteContactsPermission = false;
72631b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasReadCallLogPermission = false;
72731b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            bool hasWriteCallLogPermission = false;
72831b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn
72989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // This next group of variables is used to implement a group of
73089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // backward-compatibility heuristics necessitated by the addition of
73189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // some new uses-feature constants in 2.1 and 2.2. In most cases, the
73289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // heuristic is "if an app requests a permission but doesn't explicitly
73389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // request the corresponding <uses-feature>, presume it's there anyway".
73489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specCameraFeature = false; // camera-related
73589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specCameraAutofocusFeature = false;
73689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqCameraAutofocusFeature = false;
73789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqCameraFlashFeature = false;
738e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn            bool hasCameraPermission = false;
73989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specLocationFeature = false; // location-related
74089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specNetworkLocFeature = false;
74189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqNetworkLocFeature = false;
742ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            bool specGpsFeature = false;
74389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqGpsFeature = false;
74489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasMockLocPermission = false;
74589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasCoarseLocPermission = false;
746ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            bool hasGpsPermission = false;
74789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasGeneralLocPermission = false;
74889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specBluetoothFeature = false; // Bluetooth API-related
74989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasBluetoothPermission = false;
75089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specMicrophoneFeature = false; // microphone-related
75189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasRecordAudioPermission = false;
75289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specWiFiFeature = false;
75389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasWiFiPermission = false;
75489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specTelephonyFeature = false; // telephony-related
75589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqTelephonySubFeature = false;
75689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool hasTelephonyPermission = false;
75789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specTouchscreenFeature = false; // touchscreen-related
75889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool specMultitouchFeature = false;
75989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            bool reqDistinctMultitouchFeature = false;
760e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            bool specScreenPortraitFeature = false;
761e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            bool specScreenLandscapeFeature = false;
762f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            bool reqScreenPortraitFeature = false;
763f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            bool reqScreenLandscapeFeature = false;
76489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // 2.2 also added some other features that apps can request, but that
76589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // have no corresponding permission, so we cannot implement any
76689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // back-compatibility heuristic for them. The below are thus unnecessary
76789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // (but are retained here for documentary purposes.)
76889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specCompassFeature = false;
76989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specAccelerometerFeature = false;
77089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specProximityFeature = false;
77189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specAmbientLightFeature = false;
77289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            //bool specLiveWallpaperFeature = false;
77389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
774723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int targetSdk = 0;
775723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int smallScreen = 1;
776723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int normalScreen = 1;
777723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            int largeScreen = 1;
778f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            int xlargeScreen = 1;
779a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            int anyDensity = 1;
780e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int requiresSmallestWidthDp = 0;
781e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int compatibleWidthLimitDp = 0;
782e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            int largestWidthLimitDp = 0;
7837ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            String8 pkg;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityName;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityLabel;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 activityIcon;
7877ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu            String8 receiverName;
7881b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            String8 serviceName;
789eaeb19048672337714c1724de7992be8cb3f2124Michael Wright            Vector<String8> supportedInput;
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code == ResXMLTree::END_TAG) {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    depth--;
7931b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (depth < 2) {
794eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        if (withinSupportsInput && !supportedInput.isEmpty()) {
795eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            printf("supports-input: '");
796eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            const size_t N = supportedInput.size();
797eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            for (size_t i=0; i<N; i++) {
798eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                printf("%s", supportedInput[i].string());
799eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                if (i != N - 1) {
800eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    printf("' '");
801eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                } else {
802eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    printf("'\n");
803eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                }
804eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
805eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            supportedInput.clear();
806eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        }
8071b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinApplication = false;
808eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        withinSupportsInput = false;
8091b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (depth < 3) {
8101b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity && isMainActivity && isLauncherActivity) {
8111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            const char *aName = getComponentName(pkg, activityName);
812e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            printf("launchable-activity:");
8131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (aName != NULL) {
814e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                printf(" name='%s' ", aName);
8151b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
816e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            printf(" label='%s' icon='%s'\n",
8171b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                    activityLabel.string(),
8181b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                    activityIcon.string());
8191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
8201b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (!hasIntentFilter) {
8211b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherActivities |= withinActivity;
8221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherReceivers |= withinReceiver;
8231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            hasOtherServices |= withinService;
824d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        } else {
825d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            if (withinService) {
826d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
827d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                        hasBindNfcServicePermission);
828d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
829d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                        hasBindNfcServicePermission);
830d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            }
8311b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
8321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinActivity = false;
8331b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinService = false;
8341b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinReceiver = false;
8351b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        hasIntentFilter = false;
8361b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        isMainActivity = isLauncherActivity = false;
8371b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    } else if (depth < 4) {
8381b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinIntentFilter) {
8391b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (withinActivity) {
8401b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasMainActivity |= actMainActivity;
8411b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasOtherActivities |= !actMainActivity;
8421b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (withinReceiver) {
8431b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasWidgetReceivers |= actWidgetReceivers;
844b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
845b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                        hasBindDeviceAdminPermission);
846b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
8471b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (withinService) {
8481b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasImeService |= actImeService;
8491b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                hasWallpaperService |= actWallpaperService;
850b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                hasAccessibilityService |= (actAccessibilityService &&
851b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                        hasBindAccessibilityServicePermission);
852b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                hasPrintService |= (actPrintService && hasBindPrintServicePermission);
853b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                hasOtherServices |= (!actImeService && !actWallpaperService &&
854d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                        !actAccessibilityService && !actPrintService &&
855d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                        !actHostApduService && !actOffHostApduService);
8561b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
8571b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
8581b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        withinIntentFilter = false;
8591b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (code != ResXMLTree::START_TAG) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                depth++;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 tag(tree.getElementName(&len));
8671b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                //printf("Depth %d,  %s\n", depth, tag.string());
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (depth == 1) {
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (tag != "manifest") {
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8737ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    pkg = getAttribute(tree, NULL, "package", NULL);
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("package: name='%s' ", pkg.string());
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (versionCode > 0) {
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("versionCode='%d' ", versionCode);
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        printf("versionCode='' ");
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
885cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (error != "") {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        goto bail;
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    printf("versionName='%s'\n", versionName.string());
8917ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                } else if (depth == 2) {
8927ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinApplication = false;
8937ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    if (tag == "application") {
8947ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        withinApplication = true;
895e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
896e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        String8 label;
897e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        const size_t NL = locales.size();
898e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        for (size_t i=0; i<NL; i++) {
899e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            const char* localeStr =  locales[i].string();
900e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            assets.setLocale(localeStr != NULL ? localeStr : "");
901e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
902e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            if (llabel != "") {
903e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                if (localeStr == NULL || strlen(localeStr) == 0) {
904e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    label = llabel;
905e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    printf("application-label:'%s'\n", llabel.string());
906e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                } else {
907e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    if (label == "") {
908e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                        label = llabel;
909e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    }
910e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                    printf("application-label-%s:'%s'\n", localeStr,
911e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                            llabel.string());
912e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                }
913e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            }
9147ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
915e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
916e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        ResTable_config tmpConfig = config;
917e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        const size_t ND = densities.size();
918e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        for (size_t i=0; i<ND; i++) {
919e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            tmpConfig.density = densities[i];
920e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            assets.setConfiguration(tmpConfig);
921e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
922e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            if (icon != "") {
923e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                printf("application-icon-%d:'%s'\n", densities[i], icon.string());
924e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            }
925e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        }
926e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        assets.setConfiguration(config);
927e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
9287ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
9297ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
9307ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
9317ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
9327ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
933bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
9347ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        if (error != "") {
935bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
9367ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            goto bail;
9377ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
938e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        printf("application: label='%s' ", label.string());
939e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        printf("icon='%s'\n", icon.string());
940bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (testOnly != 0) {
941bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("testOnly='%d'\n", testOnly);
942bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
943b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill
944b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
945b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        if (error != "") {
946b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
947b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                            goto bail;
948b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        }
949b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        if (debuggable != 0) {
950b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                            printf("application-debuggable\n");
951b6ec11ef372a498c4d5fd2317a015b808495a2edDan Morrill                        }
952bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    } else if (tag == "uses-sdk") {
953bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
954bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (error != "") {
955bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            error = "";
956bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
957bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (error != "") {
958bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
959bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                        error.string());
960bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                goto bail;
961bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
962723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (name == "Donut") targetSdk = 4;
963bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("sdkVersion:'%s'\n", name.string());
964bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        } else if (code != -1) {
965723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            targetSdk = code;
966bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("sdkVersion:'%d'\n", code);
967bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
96875c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
96975c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        if (code != -1) {
97075c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                            printf("maxSdkVersion:'%d'\n", code);
97175c498426a17b47d445711bb9e36794b05876a56Suchi Amalapurapu                        }
972bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
973bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (error != "") {
974bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            error = "";
975bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
976bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (error != "") {
977bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
978bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                        error.string());
979bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                goto bail;
980bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
981723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
982bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("targetSdkVersion:'%s'\n", name.string());
983bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        } else if (code != -1) {
984723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            if (targetSdk < code) {
985723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                targetSdk = code;
986723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                            }
987bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf("targetSdkVersion:'%d'\n", code);
988bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
989bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    } else if (tag == "uses-configuration") {
990bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqTouchScreen = getIntegerAttribute(tree,
991bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
992bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqKeyboardType = getIntegerAttribute(tree,
993bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
994bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
995bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
996bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqNavigation = getIntegerAttribute(tree,
997bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_NAVIGATION_ATTR, NULL, 0);
998bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
999bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
1000cb2d50d0d6e2e37ae02b014999da23ecd32038b8Dianne Hackborn                        printf("uses-configuration:");
1001bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqTouchScreen != 0) {
1002bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqTouchScreen='%d'", reqTouchScreen);
1003bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
1004bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqKeyboardType != 0) {
1005bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqKeyboardType='%d'", reqKeyboardType);
1006bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
1007bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqHardKeyboard != 0) {
1008bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqHardKeyboard='%d'", reqHardKeyboard);
1009bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
1010bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqNavigation != 0) {
1011bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqNavigation='%d'", reqNavigation);
10127ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
1013bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        if (reqFiveWayNav != 0) {
1014bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            printf(" reqFiveWayNav='%d'", reqFiveWayNav);
1015bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        }
1016bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        printf("\n");
1017eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                    } else if (tag == "supports-input") {
1018eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        withinSupportsInput = true;
1019723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                    } else if (tag == "supports-screens") {
1020723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        smallScreen = getIntegerAttribute(tree,
1021723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                SMALL_SCREEN_ATTR, NULL, 1);
1022723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        normalScreen = getIntegerAttribute(tree,
1023723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                NORMAL_SCREEN_ATTR, NULL, 1);
1024723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                        largeScreen = getIntegerAttribute(tree,
1025723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                                LARGE_SCREEN_ATTR, NULL, 1);
1026f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn                        xlargeScreen = getIntegerAttribute(tree,
1027f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn                                XLARGE_SCREEN_ATTR, NULL, 1);
1028a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        anyDensity = getIntegerAttribute(tree,
1029a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                                ANY_DENSITY_ATTR, NULL, 1);
1030e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        requiresSmallestWidthDp = getIntegerAttribute(tree,
1031e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
1032e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        compatibleWidthLimitDp = getIntegerAttribute(tree,
1033e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
1034e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        largestWidthLimitDp = getIntegerAttribute(tree,
1035e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
1036e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                    } else if (tag == "uses-feature") {
1037e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
103840b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu
103940b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu                        if (name != "" && error == "") {
1040e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            int req = getIntegerAttribute(tree,
1041e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    REQUIRED_ATTR, NULL, 1);
104289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
1043e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (name == "android.hardware.camera") {
1044e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                specCameraFeature = true;
104589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.camera.autofocus") {
104689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
104789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational camera permission
104889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqCameraAutofocusFeature = reqCameraAutofocusFeature || req;
104989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specCameraAutofocusFeature = true;
105089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (req && (name == "android.hardware.camera.flash")) {
105189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
105289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational camera permission
105389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqCameraFlashFeature = true;
105489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.location") {
105589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specLocationFeature = true;
105689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.location.network") {
105789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specNetworkLocFeature = true;
105889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqNetworkLocFeature = reqNetworkLocFeature || req;
1059ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                            } else if (name == "android.hardware.location.gps") {
1060ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                                specGpsFeature = true;
106189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqGpsFeature = reqGpsFeature || req;
106289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.bluetooth") {
106389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specBluetoothFeature = true;
106489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen") {
106589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specTouchscreenFeature = true;
106689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen.multitouch") {
106789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specMultitouchFeature = true;
106889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
106989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req;
107089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.microphone") {
107189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specMicrophoneFeature = true;
107289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.wifi") {
107389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specWiFiFeature = true;
107489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.hardware.telephony") {
107589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                specTelephonyFeature = true;
107689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (req && (name == "android.hardware.telephony.gsm" ||
107789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                               name == "android.hardware.telephony.cdma")) {
107889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // these have no corresponding permission to check for,
107989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                // but should imply the foundational telephony permission
108089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                reqTelephonySubFeature = true;
1081e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            } else if (name == "android.hardware.screen.portrait") {
1082e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                specScreenPortraitFeature = true;
1083e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                            } else if (name == "android.hardware.screen.landscape") {
1084e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                                specScreenLandscapeFeature = true;
1085e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
1086e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            printf("uses-feature%s:'%s'\n",
1087e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    req ? "" : "-not-required", name.string());
1088e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        } else {
1089e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            int vers = getIntegerAttribute(tree,
1090e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    GL_ES_VERSION_ATTR, &error);
1091e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (error == "") {
1092e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                printf("uses-gl-es:'0x%x'\n", vers);
1093e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
1094e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        }
1095e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                    } else if (tag == "uses-permission") {
1096e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
109740b94725dc1c62ea66db0b9502dd81b97dd3e35fSuchi Amalapurapu                        if (name != "" && error == "") {
1098e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            if (name == "android.permission.CAMERA") {
1099e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                hasCameraPermission = true;
1100ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                            } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
1101ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                                hasGpsPermission = true;
110289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_MOCK_LOCATION") {
110389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasMockLocPermission = true;
110489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
110589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasCoarseLocPermission = true;
110689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
110789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.INSTALL_LOCATION_PROVIDER") {
110889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasGeneralLocPermission = true;
110989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.BLUETOOTH" ||
111089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.BLUETOOTH_ADMIN") {
111189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasBluetoothPermission = true;
111289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.RECORD_AUDIO") {
111389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasRecordAudioPermission = true;
111489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
111589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CHANGE_WIFI_STATE" ||
111689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
111789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasWiFiPermission = true;
111889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                            } else if (name == "android.permission.CALL_PHONE" ||
111989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.CALL_PRIVILEGED" ||
112089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.MODIFY_PHONE_STATE" ||
112189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.PROCESS_OUTGOING_CALLS" ||
112289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.READ_SMS" ||
112389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_SMS" ||
112489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_MMS" ||
112589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.RECEIVE_WAP_PUSH" ||
112689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.SEND_SMS" ||
112789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.WRITE_APN_SETTINGS" ||
112889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                       name == "android.permission.WRITE_SMS") {
112989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                                hasTelephonyPermission = true;
1130063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                            } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
1131063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                                hasWriteExternalStoragePermission = true;
11327924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                            } else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
11337924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                                hasReadExternalStoragePermission = true;
1134063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                            } else if (name == "android.permission.READ_PHONE_STATE") {
1135063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                                hasReadPhoneStatePermission = true;
113631b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.READ_CONTACTS") {
113731b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasReadContactsPermission = true;
113831b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.WRITE_CONTACTS") {
113931b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasWriteContactsPermission = true;
114031b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.READ_CALL_LOG") {
114131b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasReadCallLogPermission = true;
114231b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                            } else if (name == "android.permission.WRITE_CALL_LOG") {
114331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                                hasWriteCallLogPermission = true;
1144e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            }
1145e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            printf("uses-permission:'%s'\n", name.string());
11461bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                            int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1);
11471bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                            if (!req) {
11481bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                                printf("optional-permission:'%s'\n", name.string());
11491bcc3d691fd1cb68abced62caf3024e2bb228561Nick Kralevich                            }
1150e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        } else {
1151e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1152e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                                    error.string());
1153e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                            goto bail;
1154e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn                        }
115543b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                    } else if (tag == "uses-package") {
115643b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        String8 name = getAttribute(tree, NAME_ATTR, &error);
115743b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        if (name != "" && error == "") {
115843b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                            printf("uses-package:'%s'\n", name.string());
115943b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        } else {
116043b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
116143b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                                    error.string());
116243b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                                goto bail;
116343b6803095e41e6a1cf844a77813c6cdbdc84ec3Dianne Hackborn                        }
1164e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                    } else if (tag == "original-package") {
1165e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1166e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        if (name != "" && error == "") {
1167e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                            printf("original-package:'%s'\n", name.string());
1168e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        } else {
1169e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1170e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                                    error.string());
1171e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                                goto bail;
1172e2c17f9174144a6eca3fdbed8d5d1370f318f549Jeff Hamilton                        }
1173096b67f65510a5076f1f845f9e19dda2b30ea6bbDan Morrill                    } else if (tag == "supports-gl-texture") {
11746f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        String8 name = getAttribute(tree, NAME_ATTR, &error);
11756f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        if (name != "" && error == "") {
1176096b67f65510a5076f1f845f9e19dda2b30ea6bbDan Morrill                            printf("supports-gl-texture:'%s'\n", name.string());
11776f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        } else {
11786f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
11796f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                                    error.string());
11806f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                                goto bail;
11816f51fc14d0c3df8f9153ae5df992cc2731f099c8Dan Morrill                        }
1182a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                    } else if (tag == "compatible-screens") {
1183a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        printCompatibleScreens(tree);
1184a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn                        depth--;
118556088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                    } else if (tag == "package-verifier") {
118656088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        String8 name = getAttribute(tree, NAME_ATTR, &error);
118756088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        if (name != "" && error == "") {
118856088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
118956088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            if (publicKey != "" && error == "") {
119056088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                                printf("package-verifier: name='%s' publicKey='%s'\n",
119156088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                                        name.string(), publicKey.string());
119256088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                            }
119356088a55ca6c9277f09040a7883117cb127e1e56Kenny Root                        }
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1195eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                } else if (depth == 3) {
11967ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinActivity = false;
11977ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    withinReceiver = false;
11981b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    withinService = false;
11991b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    hasIntentFilter = false;
1200d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasMetaHostPaymentCategory = false;
1201d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasMetaOffHostPaymentCategory = false;
1202d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasBindDeviceAdminPermission = false;
1203d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasBindInputMethodPermission = false;
1204d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasBindAccessibilityServicePermission = false;
1205d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasBindPrintServicePermission = false;
1206d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    hasBindNfcServicePermission = false;
1207eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                    if (withinApplication) {
1208eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        if(tag == "activity") {
1209eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            withinActivity = true;
1210eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            activityName = getAttribute(tree, NAME_ATTR, &error);
1211eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1212eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1213eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        error.string());
1214eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1215eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1217eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
1218eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1219eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
1220eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        error.string());
1221eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1222eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1224eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
1225eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1226eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
1227eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        error.string());
1228eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1229eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1230f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn
1231eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            int32_t orien = getResolvedIntegerAttribute(&res, tree,
1232eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    SCREEN_ORIENTATION_ATTR, &error);
1233eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error == "") {
1234eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                if (orien == 0 || orien == 6 || orien == 8) {
1235eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    // Requests landscape, sensorLandscape, or reverseLandscape.
1236eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    reqScreenLandscapeFeature = true;
1237eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                } else if (orien == 1 || orien == 7 || orien == 9) {
1238eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    // Requests portrait, sensorPortrait, or reversePortrait.
1239eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    reqScreenPortraitFeature = true;
1240eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                }
1241f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                            }
1242eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else if (tag == "uses-library") {
1243eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
1244eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1245eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr,
1246eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        "ERROR getting 'android:name' attribute for uses-library"
1247eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        " %s\n", error.string());
1248eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1249eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1250eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            int req = getIntegerAttribute(tree,
1251eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    REQUIRED_ATTR, NULL, 1);
1252eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            printf("uses-library%s:'%s'\n",
1253eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    req ? "" : "-not-required", libraryName.string());
1254eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else if (tag == "receiver") {
1255eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            withinReceiver = true;
1256eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            receiverName = getAttribute(tree, NAME_ATTR, &error);
12577ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
1258eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1259eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr,
1260eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        "ERROR getting 'android:name' attribute for receiver:"
1261eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        " %s\n", error.string());
1262eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1263eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1264b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski
1265b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1266b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            if (error == "") {
1267b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                if (permission == "android.permission.BIND_DEVICE_ADMIN") {
1268b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                    hasBindDeviceAdminPermission = true;
1269b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                }
1270b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            } else {
1271b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1272b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                        " receiver '%s': %s\n", receiverName.string(), error.string());
1273b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            }
1274eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else if (tag == "service") {
1275eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            withinService = true;
1276eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            serviceName = getAttribute(tree, NAME_ATTR, &error);
12771b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1278eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            if (error != "") {
1279eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                fprintf(stderr, "ERROR getting 'android:name' attribute for"
1280eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                        " service: %s\n", error.string());
1281eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                goto bail;
1282eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            }
1283b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski
1284b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
1285b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            if (error == "") {
1286b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                if (permission == "android.permission.BIND_INPUT_METHOD") {
1287b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                    hasBindInputMethodPermission = true;
1288b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
1289b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                    hasBindAccessibilityServicePermission = true;
1290b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
1291b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                    hasBindPrintServicePermission = true;
1292d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                } else if (permission == "android.permission.BIND_NFC_SERVICE") {
1293d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                    hasBindNfcServicePermission = true;
1294b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                }
1295b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            } else {
1296b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                fprintf(stderr, "ERROR getting 'android:permission' attribute for"
1297b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                        " service '%s': %s\n", serviceName.string(), error.string());
1298b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            }
1299eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        }
1300eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                    } else if (withinSupportsInput && tag == "input-type") {
1301eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1302eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        if (name != "" && error == "") {
1303eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            supportedInput.add(name);
1304eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                        } else {
1305eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
1306eaeb19048672337714c1724de7992be8cb3f2124Michael Wright                                    error.string());
13071b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
13081b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
13097ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    }
1310d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                } else if (depth == 4) {
1311d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    if (tag == "intent-filter") {
1312d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        hasIntentFilter = true;
1313d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        withinIntentFilter = true;
1314d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actMainActivity = false;
1315d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actWidgetReceivers = false;
1316d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actImeService = false;
1317d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actWallpaperService = false;
1318d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actAccessibilityService = false;
1319d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actPrintService = false;
1320d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actDeviceAdminEnabled = false;
1321d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actHostApduService = false;
1322d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        actOffHostApduService = false;
1323d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    } else if (withinService && tag == "meta-data") {
1324d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        String8 name = getAttribute(tree, NAME_ATTR, &error);
1325d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        if (error != "") {
1326d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            fprintf(stderr, "ERROR getting 'android:name' attribute for"
1327d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                    " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
1328d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            goto bail;
1329d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        }
1330d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
1331d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        if (name == "android.nfc.cardemulation.host_apdu_service" ||
1332d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                name == "android.nfc.cardemulation.off_host_apdu_service") {
1333d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            bool offHost = true;
1334d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            if (name == "android.nfc.cardemulation.host_apdu_service") {
1335d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                offHost = false;
1336d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            }
1337d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
1338d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
1339d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            if (error != "") {
1340d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                fprintf(stderr, "ERROR getting 'android:resource' attribute for"
1341d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                        " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
1342d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                goto bail;
1343d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            }
1344d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
1345d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
1346d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                    offHost, &error);
1347d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            if (error != "") {
1348d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                fprintf(stderr, "ERROR getting AID category for service '%s'\n",
1349d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                        serviceName.string());
1350d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                goto bail;
1351d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            }
1352d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski
1353d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            const size_t catLen = categories.size();
1354d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            for (size_t i = 0; i < catLen; i++) {
1355d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                bool paymentCategory = (categories[i] == "payment");
1356d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                if (offHost) {
1357d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                    hasMetaOffHostPaymentCategory |= paymentCategory;
1358d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                } else {
1359d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                    hasMetaHostPaymentCategory |= paymentCategory;
1360d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                }
1361d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            }
1362d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                        }
1363d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                    }
13641b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                } else if ((depth == 5) && withinIntentFilter){
13651b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    String8 action;
13661b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (tag == "action") {
13671b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        action = getAttribute(tree, NAME_ATTR, &error);
13681b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
13691b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
13701b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
13711b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
13721b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity) {
1373bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            if (action == "android.intent.action.MAIN") {
1374bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                                isMainActivity = true;
13751b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actMainActivity = true;
1376bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                            }
13771b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        } else if (withinReceiver) {
13781b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
13791b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actWidgetReceivers = true;
1380b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
1381b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                actDeviceAdminEnabled = true;
13827ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            }
13831b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        } else if (withinService) {
13841b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (action == "android.view.InputMethod") {
13851b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actImeService = true;
13861b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            } else if (action == "android.service.wallpaper.WallpaperService") {
13871b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                actWallpaperService = true;
1388b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            } else if (action == "android.accessibilityservice.AccessibilityService") {
1389b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                actAccessibilityService = true;
1390b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                            } else if (action == "android.printservice.PrintService") {
1391b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                                actPrintService = true;
1392d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
1393d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                actHostApduService = true;
1394d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                            } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
1395d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                                actOffHostApduService = true;
13967ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                            }
13977ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
13981b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (action == "android.intent.action.SEARCH") {
13991b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            isSearchable = true;
14007ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                        }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14031b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                    if (tag == "category") {
14041b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        String8 category = getAttribute(tree, NAME_ATTR, &error);
14051b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (error != "") {
14061b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            fprintf(stderr, "ERROR getting 'name' attribute: %s\n", error.string());
14071b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            goto bail;
14081b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
14091b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        if (withinActivity) {
14101b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            if (category == "android.intent.category.LAUNCHER") {
14111b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                                isLauncherActivity = true;
14121b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                            }
14131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                        }
14147ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu                    }
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1417063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root
1418063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            // Pre-1.6 implicitly granted permission compatibility logic
1419063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            if (targetSdk < 4) {
1420063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                if (!hasWriteExternalStoragePermission) {
1421063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                    printf("uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE'\n");
14224aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.WRITE_EXTERNAL_STORAGE'," \
14234aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 4'\n");
14247924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                    hasWriteExternalStoragePermission = true;
1425063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                }
1426063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                if (!hasReadPhoneStatePermission) {
1427063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                    printf("uses-permission:'android.permission.READ_PHONE_STATE'\n");
14284aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.READ_PHONE_STATE'," \
14294aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 4'\n");
1430063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root                }
1431063a44e541335819b673fb1c20a338bbcaf3a3f5Kenny Root            }
14321b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
14337924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            // If the application has requested WRITE_EXTERNAL_STORAGE, we will
14342bd8d0403be62df679f0f94ab4d84c9ae9a2e918Dianne Hackborn            // force them to always take READ_EXTERNAL_STORAGE as well.  We always
14352bd8d0403be62df679f0f94ab4d84c9ae9a2e918Dianne Hackborn            // do this (regardless of target API version) because we can't have
14362bd8d0403be62df679f0f94ab4d84c9ae9a2e918Dianne Hackborn            // an app with write permission but not read permission.
14377924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
14387924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn                printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
14394aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-permission:'android.permission.READ_EXTERNAL_STORAGE'," \
14404aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested WRITE_EXTERNAL_STORAGE'\n");
14417924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn            }
14427924512aa12c6af37d90e8ccfcdf04eb78a294a3Dianne Hackborn
144331b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            // Pre-JellyBean call log permission compatibility.
144431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            if (targetSdk < 16) {
144531b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                if (!hasReadCallLogPermission && hasReadContactsPermission) {
144631b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                    printf("uses-permission:'android.permission.READ_CALL_LOG'\n");
14474aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.READ_CALL_LOG'," \
14484aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 16 and requested READ_CONTACTS'\n");
144931b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                }
145031b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
145131b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                    printf("uses-permission:'android.permission.WRITE_CALL_LOG'\n");
14524aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-permission:'android.permission.WRITE_CALL_LOG'," \
14534aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'targetSdkVersion < 16 and requested WRITE_CONTACTS'\n");
145431b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn                }
145531b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn            }
145631b0e0e86ad061cd8005e80817bcad017e2d56ddDianne Hackborn
145789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            /* The following blocks handle printing "inferred" uses-features, based
145889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * on whether related features or permissions are used by the app.
145989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * Note that the various spec*Feature variables denote whether the
146089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * relevant tag was *present* in the AndroidManfest, not that it was
146189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             * present and set to true.
146289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill             */
146389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Camera-related back-compatibility logic
146489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specCameraFeature) {
14654aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                if (reqCameraFlashFeature) {
146689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // if app requested a sub-feature (autofocus or flash) and didn't
146789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // request the base camera feature, we infer that it meant to
146889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    printf("uses-feature:'android.hardware.camera'\n");
14694aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.camera'," \
14704aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'requested android.hardware.camera.flash feature'\n");
14714aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                } else if (reqCameraAutofocusFeature) {
14724aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    // if app requested a sub-feature (autofocus or flash) and didn't
14734aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    // request the base camera feature, we infer that it meant to
14744aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-feature:'android.hardware.camera'\n");
14754aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.camera'," \
14764aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'requested android.hardware.camera.autofocus feature'\n");
147789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                } else if (hasCameraPermission) {
147889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // if app wants to use camera but didn't request the feature, we infer
147989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // that it meant to, and further that it wants autofocus
148089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    // (which was the 1.0 - 1.5 behavior)
148189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    printf("uses-feature:'android.hardware.camera'\n");
148289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    if (!specCameraAutofocusFeature) {
148389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                        printf("uses-feature:'android.hardware.camera.autofocus'\n");
14844aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        printf("uses-implied-feature:'android.hardware.camera.autofocus'," \
14854aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                                "'requested android.permission.CAMERA permission'\n");
148689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                    }
148789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                }
1488e5276a74746b5e8f09b05a50155e7aa0bbb4a747Dianne Hackborn            }
1489dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker
149089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Location-related back-compatibility logic
149189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specLocationFeature &&
149289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission ||
149389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                 hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) {
149489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app either takes a location-related permission or requests one of the
149589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // sub-features, we infer that it also meant to request the base location feature
149689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.location'\n");
14974aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.location'," \
14984aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested a location access permission'\n");
149989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
1500ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            if (!specGpsFeature && hasGpsPermission) {
150189d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes GPS (FINE location) perm but does not request the GPS
150289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
1503ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                printf("uses-feature:'android.hardware.location.gps'\n");
15044aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.location.gps'," \
15054aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.ACCESS_FINE_LOCATION permission'\n");
1506ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            }
150789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specNetworkLocFeature && hasCoarseLocPermission) {
150889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes Network location (COARSE location) perm but does not request the
150989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // network location feature, we infer that it meant to
151089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.location.network'\n");
15114aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.location.network'," \
1512ec559ff78caa16cffcc7b9d688fe911e8945e17dDianne Hackborn                        "'requested android.permission.ACCESS_COARSE_LOCATION permission'\n");
151389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
151489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
151589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Bluetooth-related compatibility logic
15166b22d81aa35d9a9b32670995c002e92588b2fe09Dan Morrill            if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) {
151789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes a Bluetooth permission but does not request the Bluetooth
151889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
151989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.bluetooth'\n");
15204aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.bluetooth'," \
15214aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \
15224aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "permission and targetSdkVersion > 4'\n");
152389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
152489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
152589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Microphone-related compatibility logic
152689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specMicrophoneFeature && hasRecordAudioPermission) {
152789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes the record-audio permission but does not request the microphone
152889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
152989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.microphone'\n");
15304aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.microphone'," \
15314aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.RECORD_AUDIO permission'\n");
153289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
153389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
153489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // WiFi-related compatibility logic
153589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specWiFiFeature && hasWiFiPermission) {
153689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the WiFi permissions but does not request the WiFi
153789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // feature, we infer that it meant to
153889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.wifi'\n");
15394aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.wifi'," \
15404aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.permission.ACCESS_WIFI_STATE, " \
15414aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "android.permission.CHANGE_WIFI_STATE, or " \
15424aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n");
154389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
154489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
154589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Telephony-related compatibility logic
154689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) {
154789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the telephony permissions or requests a sub-feature but
154889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // does not request the base telephony feature, we infer that it meant to
154989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.telephony'\n");
15504aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.telephony'," \
15514aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested a telephony-related permission or feature'\n");
155289d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
155389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill
155489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            // Touchscreen-related back-compatibility logic
155589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specTouchscreenFeature) { // not a typo!
155689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // all apps are presumed to require a touchscreen, unless they explicitly say
155789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
155889d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // Note that specTouchscreenFeature is true if the tag is present, regardless
155989d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // of whether its value is true or false, so this is safe
156089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.touchscreen'\n");
15614aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.touchscreen'," \
15624aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'assumed you require a touch screen unless explicitly made optional'\n");
156389d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
156489d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            if (!specMultitouchFeature && reqDistinctMultitouchFeature) {
156589d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // if app takes one of the telephony permissions or requests a sub-feature but
156689d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                // does not request the base telephony feature, we infer that it meant to
156789d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill                printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
15684aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \
15694aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                        "'requested android.hardware.touchscreen.multitouch.distinct feature'\n");
157089d97c1418c7a8b54fd57cc90daa1b1a98848bf6Dan Morrill            }
1571ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn
1572e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // Landscape/portrait-related compatibility logic
1573f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn            if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
1574f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // If the app has specified any activities in its manifest
1575f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // that request a specific orientation, then assume that
1576f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                // orientation is required.
1577f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                if (reqScreenLandscapeFeature) {
1578f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                    printf("uses-feature:'android.hardware.screen.landscape'\n");
15794aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.screen.landscape'," \
15804aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'one or more activities have specified a landscape orientation'\n");
1581f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                }
1582f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                if (reqScreenPortraitFeature) {
1583f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                    printf("uses-feature:'android.hardware.screen.portrait'\n");
15844aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                    printf("uses-implied-feature:'android.hardware.screen.portrait'," \
15854aa14b912fa7b0e8f2f1deb3e66dab4668de1e12Dianne Hackborn                            "'one or more activities have specified a portrait orientation'\n");
1586f77ae6e65a7ab47e7ab0ee1536d708b6e56fe45bDianne Hackborn                }
1587e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1588e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
15891b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasMainActivity) {
15901b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("main\n");
15911b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
15921b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasWidgetReceivers) {
15931b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("app-widget\n");
15941b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
1595b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            if (hasDeviceAdminReceiver) {
1596b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                printf("device-admin\n");
1597b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            }
15981b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasImeService) {
15991b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("ime\n");
16001b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
16011b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasWallpaperService) {
16021b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("wallpaper\n");
16031b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
1604b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            if (hasAccessibilityService) {
1605b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                printf("accessibility\n");
1606b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            }
1607b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            if (hasPrintService) {
1608b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski                printf("print\n");
1609b1249b822cef4e187814b83ae788f71842b88c28Adam Lesinski            }
1610d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            if (hasPaymentService) {
1611d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski                printf("payment\n");
1612d831e80a2fa80d18867e70927e4e8cd797ead56fAdam Lesinski            }
16131b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherActivities) {
16141b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-activities\n");
16151b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
16161b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (isSearchable) {
16171b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("search\n");
16181b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
16191b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherReceivers) {
16201b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-receivers\n");
16211b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
16221b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            if (hasOtherServices) {
16231b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu                printf("other-services\n");
16241b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu            }
16251b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1626e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // For modern apps, if screen size buckets haven't been specified
1627e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            // but the new width ranges have, then infer the buckets from them.
1628e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
1629e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    && requiresSmallestWidthDp > 0) {
1630e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                int compatWidth = compatibleWidthLimitDp;
1631e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (compatWidth <= 0) compatWidth = requiresSmallestWidthDp;
1632e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
1633e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    smallScreen = -1;
1634e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1635e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    smallScreen = 0;
1636e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1637e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
1638e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    normalScreen = -1;
1639e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1640e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    normalScreen = 0;
1641e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1642e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
1643e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    largeScreen = -1;
1644e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1645e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    largeScreen = 0;
1646e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1647e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
1648e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    xlargeScreen = -1;
1649e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                } else {
1650e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                    xlargeScreen = 0;
1651e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                }
1652e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1653e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn
1654723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // Determine default values for any unspecified screen sizes,
1655723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // based on the target SDK of the package.  As of 4 (donut)
1656723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // the screen size support was introduced, so all default to
1657723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            // enabled.
1658723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (smallScreen > 0) {
1659723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                smallScreen = targetSdk >= 4 ? -1 : 0;
1660723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1661723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (normalScreen > 0) {
1662723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                normalScreen = -1;
1663723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1664723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (largeScreen > 0) {
1665723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn                largeScreen = targetSdk >= 4 ? -1 : 0;
1666723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            }
1667f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            if (xlargeScreen > 0) {
1668d58fb97ddf052b3ceac921ac7e936af990392b2cScott Main                // Introduced in Gingerbread.
1669d58fb97ddf052b3ceac921ac7e936af990392b2cScott Main                xlargeScreen = targetSdk >= 9 ? -1 : 0;
1670f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            }
1671a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            if (anyDensity > 0) {
1672e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
1673e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                        || compatibleWidthLimitDp > 0) ? -1 : 0;
1674a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            }
1675723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            printf("supports-screens:");
1676723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (smallScreen != 0) printf(" 'small'");
1677723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (normalScreen != 0) printf(" 'normal'");
1678723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            if (largeScreen != 0) printf(" 'large'");
1679f43489d7d5e1c0c5c9a7e54c22845fcb99765f81Dianne Hackborn            if (xlargeScreen != 0) printf(" 'xlarge'");
1680723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn            printf("\n");
1681a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
1682e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (requiresSmallestWidthDp > 0) {
1683e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
1684e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1685e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (compatibleWidthLimitDp > 0) {
1686e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
1687e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1688e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            if (largestWidthLimitDp > 0) {
1689e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
1690e289bff0ec2b1af4ba773e0c8d49d5fd46eb9921Dianne Hackborn            }
1691a0b46c9c441f017a2008ca8ee2c864987465996bDianne Hackborn
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("locales:");
1693e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            const size_t NL = locales.size();
1694e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            for (size_t i=0; i<NL; i++) {
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char* localeStr =  locales[i].string();
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (localeStr == NULL || strlen(localeStr) == 0) {
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    localeStr = "--_--";
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf(" '%s'", localeStr);
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("\n");
17021b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1703e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            printf("densities:");
1704e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            const size_t ND = densities.size();
1705e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            for (size_t i=0; i<ND; i++) {
1706e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn                printf(" '%d'", densities[i]);
1707e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            }
1708e17086ba346009a26cc2299b133a0fe602acb6ecDianne Hackborn            printf("\n");
17091b125980c5de597c18a179b9b02b9a5afe106895Suchi Amalapurapu
1710bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
1711bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            if (dir != NULL) {
1712bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                if (dir->getFileCount() > 0) {
1713bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    printf("native-code:");
1714bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    for (size_t i=0; i<dir->getFileCount(); i++) {
1715bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                        printf(" '%s'", dir->getFileName(i).string());
1716bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    }
1717bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                    printf("\n");
1718bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                }
1719bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn                delete dir;
1720bb9ea30ea9e390e69602935571795d2c80dc7b91Dianne Hackborn            }
1721e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill        } else if (strcmp("badger", option) == 0) {
17226c997a9e880e08c354ffd809bd62df9e25e9c4d4Dianne Hackborn            printf("%s", CONSOLE_DATA);
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strcmp("configurations", option) == 0) {
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Vector<ResTable_config> configs;
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            res.getConfigurations(&configs);
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const size_t N = configs.size();
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t i=0; i<N; i++) {
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("%s\n", configs[i].toString().string());
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: unknown dump option '%s'\n", option);
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = NO_ERROR;
17377ef189d0a90f3c9a409512ab7dce9304639df481Suchi Amalapurapu
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (asset) {
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete asset;
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the "add" command, which wants to add files to a new or
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pre-existing archive.
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doAdd(Bundle* bundle)
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getUpdate()) {
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* avoid confusion */
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: can't use '-u' with add\n");
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: must specify zip file name\n");
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "NOTE: nothing to do\n");
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadWrite(zipFileName, true);
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName);
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fileName = bundle->getFileSpecEntry(i);
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) {
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf(" '%s'... (from gzip)\n", fileName);
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL);
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1786dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            if (bundle->getJunkPath()) {
1787dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                String8 storageName = String8(fileName).getPathLeaf();
1788dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                printf(" '%s' as '%s'...\n", fileName, storageName.string());
1789dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                result = zip->add(fileName, storageName.string(),
1790dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                                  bundle->getCompressionMethod(), NULL);
1791dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            } else {
1792dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                printf(" '%s'...\n", fileName);
1793dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker                result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
1794dbe7a68cc13ae135b33769918932838d2d447169Doug Zongker            }
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result != NO_ERROR) {
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName);
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (result == NAME_NOT_FOUND)
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, ": file not found\n");
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else if (result == ALREADY_EXISTS)
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, ": already exists in archive\n");
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            else
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "\n");
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = NO_ERROR;
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Delete files from an existing archive.
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doRemove(Bundle* bundle)
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ZipFile* zip = NULL;
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = UNKNOWN_ERROR;
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* zipFileName;
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 1) {
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: must specify zip file name\n");
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipFileName = bundle->getFileSpecEntry(0);
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getFileSpecCount() < 2) {
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "NOTE: nothing to do\n");
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = openReadWrite(zipFileName, false);
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n",
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            zipFileName);
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 1; i < bundle->getFileSpecCount(); i++) {
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* fileName = bundle->getFileSpecEntry(i);
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ZipEntry* entry;
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        entry = zip->getEntryByName(fileName);
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (entry == NULL) {
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf(" '%s' NOT FOUND\n", fileName);
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        result = zip->remove(entry);
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (result != NO_ERROR) {
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "Unable to delete '%s' from '%s'\n",
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bundle->getFileSpecEntry(i), zipFileName);
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* update the archive */
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip->flush();
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete zip;
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (result != NO_ERROR);
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Package up an asset directory and associated application files.
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint doPackage(Bundle* bundle)
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* outputAPKFile;
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int retVal = 1;
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err;
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptAssets> assets;
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N;
18819bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    FILE* fp;
18829bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    String8 dependencyFile;
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1884a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    // -c en_XA or/and ar_XB means do pseudolocalization
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResourceFilter filter;
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = filter.parse(bundle->getConfigurations());
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err != NO_ERROR) {
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (filter.containsPseudo()) {
1891a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
1892a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
1893a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    if (filter.containsPseudoBidi()) {
1894a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    N = bundle->getFileSpecCount();
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDir() == NULL) {
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "ERROR: no input files\n");
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    outputAPKFile = bundle->getOutputAPKFile();
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Make sure the filenames provided exist and are of the appropriate type.
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outputAPKFile) {
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileType type;
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        type = getFileType(outputAPKFile);
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (type != kFileTypeNonexistent && type != kFileTypeRegular) {
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr,
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "ERROR: output file '%s' exists but is not regular file\n",
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outputAPKFile);
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Load the assets.
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assets = new AaptAssets();
19209bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
192103589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    // Set up the resource gathering in assets if we're going to generate
1922b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // dependency files. Every time we encounter a resource while slurping
1923b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the tree, we'll add it to these stores so we have full resource paths
1924b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // to write to a dependency file.
19259bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    if (bundle->getGenDependencies()) {
192603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        sp<FilePathStore> resPathStore = new FilePathStore;
192703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        assets->setFullResPaths(resPathStore);
192803589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        sp<FilePathStore> assetPathStore = new FilePathStore;
192903589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        assets->setFullAssetPaths(assetPathStore);
19309bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    }
19319bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    err = assets->slurpFromArgs(bundle);
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err < 0) {
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getVerbose()) {
1938e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn        assets->print(String8());
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19419bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    // If they asked for any fileAs that need to be compiled, do so.
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = buildResources(bundle, assets);
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != 0) {
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // At this point we've read everything and processed everything.  From here
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // on out it's just writing output files.
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto bail;
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19551644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    // Update symbols with information about which ones are needed as Java symbols.
19561644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    assets->applyJavaSymbols();
19571644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    if (SourcePos::hasErrors()) {
19581644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn        goto bail;
19591644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    }
19601644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn
1961b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // If we've been asked to generate a dependency file, do that here
19629bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    if (bundle->getGenDependencies()) {
1963b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // If this is the packaging step, generate the dependency file next to
1964b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // the output apk (e.g. bin/resources.ap_.d)
196503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        if (outputAPKFile) {
196603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile = String8(outputAPKFile);
1967b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Add the .d extension to the dependency file.
196803589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile.append(".d");
196903589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        } else {
1970b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Else if this is the R.java dependency generation step,
1971b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // generate the dependency file in the R.java package subdirectory
1972b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/R.java.d
197303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin            dependencyFile = String8(bundle->getRClassDir());
1974b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            dependencyFile.appendPath("R.java.d");
197503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        }
19769bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        // Make sure we have a clean dependency file to start with
19779bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        fp = fopen(dependencyFile, "w");
19789bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin        fclose(fp);
19799bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    }
19809bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Write out R.java constants
19821644c6d7f4931d0b4fe7ea77c63b016af01a46d3Dianne Hackborn    if (!assets->havePrivateSymbols()) {
198363459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        if (bundle->getCustomPackage() == NULL) {
1984b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // Write the R.java file into the appropriate class directory
1985b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin            // e.g. gen/com/foo/app/R.java
198663459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
198763459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        } else {
198863459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            const String8 customPkg(bundle->getCustomPackage());
198963459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet            err = writeResourceSymbols(bundle, assets, customPkg, true);
199063459ad555c10de1f316d6de01fc3cd0c0aaa457Xavier Ducrohet        }
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1994002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        // If we have library files, we're going to write our R.java file into
1995002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        // the appropriate class directory for those libraries as well.
1996002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        // e.g. gen/com/foo/app/lib/R.java
1997002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        if (bundle->getExtraPackages() != NULL) {
1998002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            // Split on colon
1999002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            String8 libs(bundle->getExtraPackages());
2000002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
2001002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            while (packageString != NULL) {
2002002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                // Write the R.java file out with the correct package name
2003002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                err = writeResourceSymbols(bundle, assets, String8(packageString), true);
2004002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                if (err < 0) {
2005002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                    goto bail;
2006002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                }
2007002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang                packageString = strtok(NULL, ":");
2008002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            }
2009002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang            libs.unlockBuffer();
2010002f53770a7f6850eab4d7e381e91dc94d28968fYing Wang        }
20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err < 0) {
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20221553c82e084ac5763fb393857224145506771b99Joe Onorato    // Write out the ProGuard file
20231553c82e084ac5763fb393857224145506771b99Joe Onorato    err = writeProguardFile(bundle, assets);
20241553c82e084ac5763fb393857224145506771b99Joe Onorato    if (err < 0) {
20251553c82e084ac5763fb393857224145506771b99Joe Onorato        goto bail;
20261553c82e084ac5763fb393857224145506771b99Joe Onorato    }
20271553c82e084ac5763fb393857224145506771b99Joe Onorato
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Write the apk
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (outputAPKFile) {
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = writeAPK(bundle, assets, String8(outputAPKFile));
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != NO_ERROR) {
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputAPKFile);
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto bail;
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2037b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // If we've been asked to generate a dependency file, we need to finish up here.
2038b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the writeResourceSymbols and writeAPK functions have already written the target
2039b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // half of the dependency file, now we need to write the prerequisites. (files that
2040b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin    // the R.java file or .ap_ file depend on)
204103589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    if (bundle->getGenDependencies()) {
204203589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        // Now that writeResourceSymbols or writeAPK has taken care of writing
204303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        // the targets to our dependency file, we'll write the prereqs
204403589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fp = fopen(dependencyFile, "a+");
204503589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fprintf(fp, " : ");
204603589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        bool includeRaw = (outputAPKFile != NULL);
204703589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
2048b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // Also manually add the AndroidManifeset since it's not under res/ or assets/
2049b711f3f7ee0544685ef26a1a4b4755d5a6233dbaJosiah Gaskin        // and therefore was not added to our pathstores during slurping
205003589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
205103589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin        fclose(fp);
205203589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin    }
205303589cc65355220e0a4a0c816189a9fa25cc81fcJosiah Gaskin
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    retVal = 0;
20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbail:
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (SourcePos::hasErrors()) {
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SourcePos::printErrors(stderr);
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return retVal;
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
20618a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
20628a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin/*
20638a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * Do PNG Crunching
20648a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * PRECONDITIONS
20658a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  -S flag points to a source directory containing drawable* folders
20668a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  -C flag points to destination directory. The folder structure in the
20678a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *     source directory will be mirrored to the destination (cache) directory
20688a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *
20698a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * POSTCONDITIONS
20708a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  Destination directory will be updated to match the PNG files in
20718a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin *  the source directory.
20728a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin */
20738a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinint doCrunch(Bundle* bundle)
20748a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
20758a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "Crunching PNG Files in ");
20768a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]);
20778a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir());
20788a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
20798a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    updatePreProcessedCache(bundle);
20808a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
20818a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return NO_ERROR;
20828a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
2083e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill
2084b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet/*
2085b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet * Do PNG Crunching on a single flag
2086b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet *  -i points to a single png file
2087b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet *  -o points to a single png output file
2088b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet */
2089b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohetint doSingleCrunch(Bundle* bundle)
2090b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet{
2091b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile());
2092b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile());
2093b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet
2094b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    String8 input(bundle->getSingleCrunchInputFile());
2095b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet    String8 output(bundle->getSingleCrunchOutputFile());
2096b7de2194d54eb81b1db4b50c171ddd0339831155Xavier Ducrohet
2097c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet    if (preProcessImageToCache(bundle, input, output) != NO_ERROR) {
2098c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet        // we can't return the status_t as it gets truncate to the lower 8 bits.
2099c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet        return 42;
2100c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet    }
2101b7de2194d54eb81b1db4b50c171ddd0339831155Xavier Ducrohet
2102c75d3f5c10bf6d7718ef69c6bbc1cdf64cd8ff04Xavier Ducrohet    return NO_ERROR;
2103b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet}
2104b1f6ad82dd8d1702617a757a88430604b3131facXavier Ducrohet
2105e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrillchar CONSOLE_DATA[2925] = {
2106e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2107e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2108e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2109e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2110e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63,
2111e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83,
2112e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2113e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2114e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81,
2115e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32,
2116e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2117e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2118e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59,
2119e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2120e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2121e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59,
2122e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32,
2123e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2124e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2125e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87,
2126e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32,
2127e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2128e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2129e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58,
2130e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2131e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2132e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81,
2133e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32,
2134e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2135e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2136e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59,
2137e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2138e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2139e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59,
2140e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32,
2141e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2142e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2143e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
2144e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32,
2145e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2146e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2147e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81,
2148e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2149e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2150e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109,
2151e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32,
2152e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2153e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59,
2154e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59,
2155e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2156e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59,
2157e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46,
2158e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32,
2159e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2160e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2161e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81,
2162e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
2163e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81,
2164e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2165e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58,
2166e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32,
2167e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59,
2168e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37,
2169e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59,
2170e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2171e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59,
2172e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96,
2173e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61,
2174e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32,
2175e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61,
2176e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59,
2177e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32,
2178e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2179e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
2180e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
2181e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10,
2182e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2183e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81,
2184e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41,
2185e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2186e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81,
2187e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58,
2188e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32,
2189e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2190e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2191e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32,
2192e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2193e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58,
2194e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58,
2195e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2196e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2197e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
2198e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32,
2199e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2200e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2201e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2202e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2203e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
2204e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106,
2205e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59,
2206e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2207e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2208e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81,
2209e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32,
2210e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
2211e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2212e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59,
2213e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2214e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2215e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81,
2216e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
2217e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2218e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2219e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81,
2220e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2221e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
2222e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59,
2223e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59,
2224e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2225e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2226e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33,
2227e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32,
2228e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
2229e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46,
2230e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59,
2231e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32,
2232e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
2233e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95,
2234e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59,
2235e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2236e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2237e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45,
2238e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32,
2239e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
2240e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59,
2241e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59,
2242e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2243e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2244e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2245e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32,
2246e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
2247e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2248e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61,
2249e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2250e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
2251e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59,
2252e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59,
2253e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2254e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2255e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32,
2256e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32,
2257e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
2258e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61,
2259e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59,
2260e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2261e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2262e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32,
2263e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32,
2264e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2265e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2266e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2267e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2268e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10
2269e74763e26f760e8de23a4edfbe599a166ef6bb53Dan Morrill  };
2270