Command.cpp revision ad2d07d2d98a46babb2a9472413fe9ce5080ca76
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include "AaptXml.h" 7fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h" 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h" 92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h" 102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h> 162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h> 172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h> 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h> 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h> 212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h> 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h> 242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h> 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 28ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#ifndef AAPT_VERSION 29ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski #define AAPT_VERSION "" 30ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#endif 31ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info. All the cool kids do it. 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle) 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 0) { 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("(ignoring extra arguments)\n"); 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 40ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n"); 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only. The call fails if the file doesn't exist. 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName) 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip; 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, ZipFile::kOpenReadOnly); 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' not found\n", fileName); 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == PERMISSION_DENIED) { 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileName); 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write. The file will be created if it doesn't 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set. 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate) 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int flags; 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags = ZipFile::kOpenReadWrite; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (okayToCreate) { 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags |= ZipFile::kOpenCreate; 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, flags); 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = NULL; 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method. 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method) 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (method == ZipEntry::kCompressStored) { 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Stored"; 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (method == ZipEntry::kCompressDeflated) { 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Deflated"; 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Unknown"; 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression). 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen) 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!uncompressedLen) { 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing. 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip" 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command. 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle) 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ZipEntry* entry; 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long totalUncLen, totalCompLen; 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 1) { 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: specify zip file name (only)\n"); 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadOnly(zipFileName); 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int count, i; 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Archive: %s\n", zipFileName); 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen = totalCompLen = 0; 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski count = zip->getNumEntries(); 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i = 0; i < count; i++) { 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByIndex(i); 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char dateBuf[32]; 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time_t when; 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski when = entry->getModWhen(); 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localtime(&when)); 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getUncompressedLen(), 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compressionName(entry->getCompressionMethod()), 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getCompressedLen(), 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(entry->getUncompressedLen(), 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCompressedLen()), 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (size_t) entry->getLFHOffset(), 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dateBuf, 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCRC32(), 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getFileName()); 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", entry->getFileName()); 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen += entry->getUncompressedLen(); 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen += entry->getCompressedLen(); 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------- --- -------\n"); 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %7ld %2d%% %d files\n", 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen, 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen, 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(totalUncLen, totalCompLen), 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->getNumEntries()); 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getAndroidList()) { 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(zipFileName), NULL)) { 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo resource table found.\n"); 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nResource table:\n"); 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(false); 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 245ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, 24676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu uint32_t attrRes, String8 attrLabel, String8* outError) 24776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 24876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 249ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError); 25076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 25176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 25376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 25476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 255ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError); 2562675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 2572675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 25976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 26076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 26176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 26276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 272a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 2739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 2749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 27594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 297caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski INSTALL_LOCATION_ATTR = 0x010102b7, 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 30494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 3050a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3082675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3172675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3192675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3229cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 3409cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 3419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 3429cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 3439cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 3449cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 3459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 347ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenSize = AaptXml::getIntegerAttribute(tree, 348ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_SIZE_ATTR); 349ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenDensity = AaptXml::getIntegerAttribute(tree, 350ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_DENSITY_ATTR); 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 36358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) { 36458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 36558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 36658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 36758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 36858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 36958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 37058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 37158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 37258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 37358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 37858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 37958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 38058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) { 38158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-implied-permission: name='%s' reason='%s'\n", 38258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string(), 38358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(reason.string()).string()); 38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 38694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, 38794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 38894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 38994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 39094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 39194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 39294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 39394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 39494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 39594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 39694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 39794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 39894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 39994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 40194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 40294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 40394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 40594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 40694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 40794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 40894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 4109cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4119cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4129cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4139cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4149cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 41694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 41794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 41894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 41994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 42094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 4239cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4249cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4259cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 42994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 43094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 43194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 43294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 43394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 43494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 436ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error); 43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 44094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 44294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 4519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 4529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 4539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 4549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 4552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to 4572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason. 4582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature { 4602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Name of the implied feature. 4622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name; 4642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * List of human-readable reasons for why this feature was implied. 4672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski SortedVector<String8> reasons; 4692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 4702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml 4732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup { 475d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup() : openGLESVersion(-1) {} 476d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 4772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Human readable label 4792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 label; 4812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Explicit features defined in the group 4842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, bool> features; 486d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 487d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski /** 488d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski * OpenGL ES version required 489d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski */ 490d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int openGLESVersion; 4912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 4922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures, 4942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const char* name, const char* reason) { 4952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name8(name); 4962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ssize_t idx = impliedFeatures->indexOfKey(name8); 4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (idx < 0) { 4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski idx = impliedFeatures->add(name8, ImpliedFeature()); 4992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).name = name8; 5002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).reasons.add(String8(reason)); 5022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp, 5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) { 5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("feature-group: label='%s'\n", grp.label.string()); 5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 508d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (grp.openGLESVersion > 0) { 509d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski printf(" uses-gl-es: '0x%x'\n", grp.openGLESVersion); 510d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 511d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 5122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatures = grp.features.size(); 5132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatures; i++) { 5142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features[i]) { 5152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 5162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const String8& featureName = grp.features.keyAt(i); 5192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", 5202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ResTable::normalizeForOutput(featureName.string()).string()); 5212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numImpliedFeatures = 5242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski (impliedFeatures != NULL) ? impliedFeatures->size() : 0; 5252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numImpliedFeatures; i++) { 5262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i); 5272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(impliedFeature.name) >= 0) { 5282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // The feature is explicitly set, no need to use implied 5292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // definition. 5302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 5312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 printableFeatureName(ResTable::normalizeForOutput( 5342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeature.name.string())); 5352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", printableFeatureName.string()); 5362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-implied-feature: name='%s' reason='", 5372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printableFeatureName.string()); 5382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numReasons = impliedFeature.reasons.size(); 5392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numReasons; j++) { 5402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("%s", impliedFeature.reasons[j].string()); 5412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (j + 2 < numReasons) { 5422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", "); 5432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (j + 1 < numReasons) { 5442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", and "); 5452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("'\n"); 5482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) { 5522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (name == "android.hardware.camera.autofocus" || 5532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.camera.flash") { 5542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.camera"), true); 5552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.location.gps" || 5562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.location.network") { 5572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.location"), true); 5582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 5592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 5602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct") { 5612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen.multitouch"), true); 5622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 563d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else if (name == "android.hardware.opengles.aep") { 564d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski const int openGLESVersion31 = 0x00030001; 565d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (openGLESVersion31 > grp->openGLESVersion) { 566d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp->openGLESVersion = openGLESVersion31; 567d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 5682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 593f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 60591447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 616c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 62263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 62325e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (res.getError() != NO_ERROR) { 62425e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 62563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 62663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski } 62763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 6282cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // The dynamicRefTable can be null if there are no resources for this asset cookie. 6292cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // This fine. 63063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); 631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski Asset* asset = NULL; 63363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 65163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 65263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 67863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 68463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 69663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); 697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 7239cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 7249cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 7259cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 7269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 7279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 7289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 735ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 7362675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "permission") { 738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 739ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 7442675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("permission: %s\n", 7452675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "uses-permission") { 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 748ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 75358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 754ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 755ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 7810a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 784ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 7852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski bool withinFeatureGroup = false; 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 7889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 7949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 7959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 798a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 799a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 801a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 80294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 8039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 8049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 8059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 8069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 8079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 808eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 812a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 815a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 816a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 81794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 81894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 8199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 8209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 821eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 8229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 8249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 82594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 82694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 827a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 828a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 829a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 833a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 83494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 8359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 8369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 837eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 853e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If an app declares itself as multiArch, we report the 854e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // native libraries differently. 855e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool hasMultiArch = false; 856e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 8622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 8860a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 889ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 8902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 8912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup commonFeatures; 8922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski Vector<FeatureGroup> featureGroups; 8932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, ImpliedFeature> impliedFeatures; 8942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 899ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 900ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 901ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 902ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 9032675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 9042675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 905ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 906ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 907ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 908ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 909ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 910ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 911ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.clear(); 912ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 914ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = false; 9152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = false; 916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 3) { 9170a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (withinActivity && isMainActivity) { 9182675f769673f69b0661ddee346292f25cb30a296Maurice Chu String8 aName(getComponentName(pkg, activityName)); 9190a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLauncherActivity) { 9200a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("launchable-activity:"); 9219eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 9229eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 9239eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 9240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9250a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s'\n", 9269eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 9279eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string()); 9280a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9290a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLeanbackLauncherActivity) { 9300a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("leanback-launchable-activity:"); 9319eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 9329eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 9339eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 9340a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9350a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s' banner='%s'\n", 9369eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 9379eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string(), 9389eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityBanner.string()).string()); 939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasIntentFilter) { 942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherActivities |= withinActivity; 943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherReceivers |= withinReceiver; 944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherServices |= withinService; 94594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 94694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (withinService) { 94794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && 94894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 94994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && 95094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 95194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 9569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 9580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; 959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 4) { 960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinIntentFilter) { 961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinActivity) { 962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMainActivity |= actMainActivity; 9639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasLauncher |= catLauncher; 9649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraActivity |= actCamera; 9659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraSecureActivity |= actCameraSecure; 9669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; 967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinReceiver) { 968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWidgetReceivers |= actWidgetReceivers; 969a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasDeviceAdminReceiver |= (actDeviceAdminEnabled && 970a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission); 971a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); 972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinService) { 973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasImeService |= actImeService; 974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWallpaperService |= actWallpaperService; 975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasAccessibilityService |= (actAccessibilityService && 976a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission); 977a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasPrintService |= (actPrintService && hasBindPrintServicePermission); 9789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasNotificationListenerService |= actNotificationListenerService && 9799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission; 980eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasDreamService |= actDreamService && hasBindDreamServicePermission; 981a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherServices |= (!actImeService && !actWallpaperService && 98294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski !actAccessibilityService && !actPrintService && 9839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actHostApduService && !actOffHostApduService && 9849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actNotificationListenerService); 9859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 9869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; 987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinIntentFilter = false; 990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 9979cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski 9989cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 9999cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 10009cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 10019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 10029cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 10039cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d, %s\n", depth, tag.string()); 1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1010ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 10112675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: name='%s' ", 10122675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(pkg.string()).string()); 1013ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR, 1014ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1016ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", 1017ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (versionCode > 0) { 1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='%d' ", versionCode); 1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='' "); 1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1025ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 versionName = AaptXml::getResolvedAttribute(res, tree, 1026ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski VERSION_NAME_ATTR, &error); 1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1028ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", 1029ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 103225d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("versionName='%s'", 10332675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(versionName.string()).string()); 103425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski 1035ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 splitName = AaptXml::getAttribute(tree, NULL, "split"); 103625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski if (!splitName.isEmpty()) { 103725d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf(" split='%s'", ResTable::normalizeForOutput( 103825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski splitName.string()).string()); 103925d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski } 1040ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 1041ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t platformVersionCode = AaptXml::getIntegerAttribute(tree, NULL, 1042ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski "platformBuildVersionCode"); 1043ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printf(" platformBuildVersionCode='%d'", platformVersionCode); 104425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("\n"); 1045caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1046ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree, 1047ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski INSTALL_LOCATION_ATTR, &error); 1048caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (error != "") { 1049caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n", 1050caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski error.string()); 1051caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1052caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1053caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1054caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (installLocation >= 0) { 1055caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("install-location:'"); 1056caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski switch (installLocation) { 1057caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 0: 1058caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("auto"); 1059caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1060caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 1: 1061caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("internalOnly"); 1062caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1063caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 2: 1064caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("preferExternal"); 1065caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1066caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski default: 1067caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "Invalid installLocation %d\n", installLocation); 1068caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1069caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1070caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("'\n"); 1071caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2) { 1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "application") { 1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = true; 1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 label; 1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setLocale(localeStr != NULL ? localeStr : ""); 1082ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, 1083ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (llabel != "") { 1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 10872675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-label:'%s'\n", 10882675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (label == "") { 1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-label-%s:'%s'\n", localeStr, 10942675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config tmpConfig = config; 1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tmpConfig.density = densities[i]; 1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(tmpConfig); 1104ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, 1105ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (icon != "") { 11072675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-icon-%d:'%s'\n", densities[i], 11082675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(icon.string()).string()); 1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1113ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error); 1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1115ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1116ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1119ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0, 1120ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1122ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", 1123ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 11262675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application: label='%s' ", 11272675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(label.string()).string()); 11282675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string()); 1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (testOnly != 0) { 1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("testOnly='%d'\n", testOnly); 1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1133ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree, 1134ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski DEBUGGABLE_ATTR, 0, &error); 1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1136ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", 1137ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (debuggable != 0) { 1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-debuggable\n"); 1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1143e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1144e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // We must search by name because the multiArch flag hasn't been API 1145e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // frozen yet. 1146e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, 1147e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski "multiArch"); 1148e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (multiArchIndex >= 0) { 1149e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski Res_value value; 1150e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) { 1151e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (value.dataType >= Res_value::TYPE_FIRST_INT && 1152e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski value.dataType <= Res_value::TYPE_LAST_INT) { 1153e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski hasMultiArch = value.data; 1154e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1155e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1156e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-sdk") { 1158ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); 1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1161ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, 1162ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski MIN_SDK_VERSION_ATTR, &error); 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", 1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut") targetSdk = 4; 11692675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("sdkVersion:'%s'\n", 11702675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("sdkVersion:'%d'\n", code); 1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1175ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR); 1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != -1) { 1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("maxSdkVersion:'%d'\n", code); 1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1179ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1182ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, 1183ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski TARGET_SDK_VERSION_ATTR, &error); 1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", 1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut" && targetSdk < 4) targetSdk = 4; 11902675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("targetSdkVersion:'%s'\n", 11912675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < code) { 1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("targetSdkVersion:'%d'\n", code); 1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-configuration") { 1199ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree, 1200ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_TOUCH_SCREEN_ATTR, 0); 1201ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree, 1202ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_KEYBOARD_TYPE_ATTR, 0); 1203ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree, 1204ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_HARD_KEYBOARD_ATTR, 0); 1205ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqNavigation = AaptXml::getIntegerAttribute(tree, 1206ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_NAVIGATION_ATTR, 0); 1207ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree, 1208ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_FIVE_WAY_NAV_ATTR, 0); 1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-configuration:"); 1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqTouchScreen != 0) { 1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqTouchScreen='%d'", reqTouchScreen); 1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqKeyboardType != 0) { 1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqKeyboardType='%d'", reqKeyboardType); 1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqHardKeyboard != 0) { 1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqHardKeyboard='%d'", reqHardKeyboard); 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqNavigation != 0) { 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqNavigation='%d'", reqNavigation); 1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqFiveWayNav != 0) { 1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqFiveWayNav='%d'", reqFiveWayNav); 1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1226ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "supports-input") { 1227ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = true; 1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-screens") { 1229ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski smallScreen = AaptXml::getIntegerAttribute(tree, 1230ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SMALL_SCREEN_ATTR, 1); 1231ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski normalScreen = AaptXml::getIntegerAttribute(tree, 1232ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski NORMAL_SCREEN_ATTR, 1); 1233ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski largeScreen = AaptXml::getIntegerAttribute(tree, 1234ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski LARGE_SCREEN_ATTR, 1); 1235ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski xlargeScreen = AaptXml::getIntegerAttribute(tree, 1236ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski XLARGE_SCREEN_ATTR, 1); 1237ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski anyDensity = AaptXml::getIntegerAttribute(tree, 1238ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ANY_DENSITY_ATTR, 1); 1239ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree, 1240ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0); 1241ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree, 1242ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0); 1243ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski largestWidthLimitDp = AaptXml::getIntegerAttribute(tree, 1244ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR, 0); 12452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (tag == "feature-group") { 12462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = true; 12472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup group; 1248ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error); 12492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (error != "") { 12502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski fprintf(stderr, "ERROR getting 'android:label' attribute:" 12512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski " %s\n", error.string()); 12522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski goto bail; 12532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 12542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski featureGroups.add(group); 12552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-feature") { 1257ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1259ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int req = AaptXml::getIntegerAttribute(tree, 1260ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRED_ATTR, 1); 1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 12622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski commonFeatures.features.add(name, req); 12632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (req) { 12642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addParentFeatures(&commonFeatures, name); 1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1267ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int vers = AaptXml::getIntegerAttribute(tree, 1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR, &error); 1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error == "") { 1270d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > commonFeatures.openGLESVersion) { 1271d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.openGLESVersion = vers; 1272d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-permission") { 1276ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "android.permission.CAMERA") { 1279d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.camera", 12802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_FINE_LOCATION") { 12832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.gps", 12842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 12862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 12872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { 12902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 12912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { 12942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.network", 12952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 12972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 12982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || 1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.INSTALL_LOCATION_PROVIDER") { 13022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.BLUETOOTH" || 1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.BLUETOOTH_ADMIN") { 13072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (targetSdk > 4) { 13082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 13092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 13112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 13122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "targetSdkVersion > 4"); 13132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.RECORD_AUDIO") { 13152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.microphone", 13162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_WIFI_STATE" || 1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_STATE" || 1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { 13212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.wifi", 13222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.CALL_PHONE" || 1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CALL_PRIVILEGED" || 1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.MODIFY_PHONE_STATE" || 1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.PROCESS_OUTGOING_CALLS" || 1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.READ_SMS" || 1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_SMS" || 1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_MMS" || 1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_WAP_PUSH" || 1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.SEND_SMS" || 1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_APN_SETTINGS" || 1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_SMS") { 13352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.telephony", 13362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8("requested a telephony permission").string()); 1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { 1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { 1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadExternalStoragePermission = true; 1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_PHONE_STATE") { 1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadPhoneStatePermission = true; 1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CONTACTS") { 1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadContactsPermission = true; 1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CONTACTS") { 1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteContactsPermission = true; 1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CALL_LOG") { 1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadCallLogPermission = true; 1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CALL_LOG") { 1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteCallLogPermission = true; 1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 135258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 135358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 1354ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 1355ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 135658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } else { 1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-package") { 1362ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13642675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("uses-package:'%s'\n", 13652675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "original-package") { 1372ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13742675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("original-package:'%s'\n", 13752675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-gl-texture") { 1382ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13842675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("supports-gl-texture:'%s'\n", 13852675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "compatible-screens") { 13929cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski printCompatibleScreens(tree, &error); 13939cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (error != "") { 13949cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR getting compatible screens: %s\n", 13959cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski error.string()); 13969cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 13979cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "package-verifier") { 1400ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1402ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error); 1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (publicKey != "" && error == "") { 1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("package-verifier: name='%s' publicKey='%s'\n", 14052675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string(), 14062675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(publicKey.string()).string()); 1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1410ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (depth == 3) { 1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 14149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 141694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory = false; 141794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory = false; 141894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindDeviceAdminPermission = false; 141994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindInputMethodPermission = false; 142094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindAccessibilityServicePermission = false; 142194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindPrintServicePermission = false; 142294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = false; 14239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes = false; 14249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = false; 1425eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = false; 1426ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinApplication) { 1427ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if(tag == "activity") { 1428ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinActivity = true; 1429ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1431ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1432ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1433ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1434ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1436ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, 1437ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1438ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1439ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", 1440ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1441ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1442ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1444ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, 1445ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1446ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1447ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1448ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1449ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1450ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1452ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, 1453ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 14540a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (error != "") { 14550a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", 14560a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn error.string()); 14570a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn goto bail; 14580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 14590a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn 1460ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree, 1461ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright SCREEN_ORIENTATION_ATTR, &error); 1462ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error == "") { 1463ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (orien == 0 || orien == 6 || orien == 8) { 1464ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests landscape, sensorLandscape, or reverseLandscape. 14652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape", 14662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a landscape orientation"); 1467ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (orien == 1 || orien == 7 || orien == 9) { 1468ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests portrait, sensorPortrait, or reversePortrait. 14692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait", 14702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a portrait orientation"); 1471ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1473ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "uses-library") { 1474ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1475ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1476ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1477ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for uses-library" 1478ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1479ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1480ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1481ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int req = AaptXml::getIntegerAttribute(tree, 1482ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRED_ATTR, 1); 1483ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("uses-library%s:'%s'\n", 14842675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", ResTable::normalizeForOutput( 14852675f769673f69b0661ddee346292f25cb30a296Maurice Chu libraryName.string()).string()); 1486ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "receiver") { 1487ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinReceiver = true; 1488ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1490ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1491ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1492ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for receiver:" 1493ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1494ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1495ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1496a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1497ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR, 1498ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1499a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1500a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_DEVICE_ADMIN") { 1501a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission = true; 1502a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1503a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1504a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1505a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " receiver '%s': %s\n", receiverName.string(), error.string()); 1506a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1507ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "service") { 1508ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinService = true; 1509ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1511ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1512ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1513ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "service:%s\n", error.string()); 1514ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1515ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1516a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1517ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR, 1518ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1519a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1520a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_INPUT_METHOD") { 1521a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindInputMethodPermission = true; 1522a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") { 1523a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission = true; 1524a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_PRINT_SERVICE") { 1525a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindPrintServicePermission = true; 152694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (permission == "android.permission.BIND_NFC_SERVICE") { 152794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = true; 15289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { 15299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = true; 1530eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (permission == "android.permission.BIND_DREAM_SERVICE") { 1531eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = true; 1532a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1533a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1534a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1535a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " service '%s': %s\n", serviceName.string(), error.string()); 1536a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 15379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (tag == "provider") { 15389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = true; 15399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1540ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski bool exported = AaptXml::getResolvedIntegerAttribute(res, tree, 1541ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski EXPORTED_ATTR, &error); 15429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:" 15449d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15459d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1548ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute( 1549ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski res, tree, GRANT_URI_PERMISSIONS_ATTR, &error); 15509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:" 15529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1556ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getResolvedAttribute(res, tree, 1557ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski PERMISSION_ATTR, &error); 15589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:" 15609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 15649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes |= exported && grantUriPermissions && 15659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski permission == "android.permission.MANAGE_DOCUMENTS"; 15669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1567ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (bundle->getIncludeMetaData() && tag == "meta-data") { 1568ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 metaDataName = AaptXml::getResolvedAttribute(res, tree, 1569ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski NAME_ATTR, &error); 1570ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1571ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1572ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "meta-data:%s\n", error.string()); 1573ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1574ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 15752675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("meta-data: name='%s' ", 15762675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(metaDataName.string()).string()); 1577ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"), 157876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu &error); 1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 158076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu // Try looking for a RESOURCE_ATTR 158176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu error = ""; 1582ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printResolvedResourceAttribute(res, tree, RESOURCE_ATTR, 158376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8("resource"), &error); 1584ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 158576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu fprintf(stderr, "ERROR getting 'android:value' or " 158676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "'android:resource' attribute for " 158776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "meta-data:%s\n", error.string()); 1588ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1589ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1590ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 159176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("\n"); 1592ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (withinSupportsInput && tag == "input-type") { 1593ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1594ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (name != "" && error == "") { 1595ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.add(name); 1596ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1597ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1598ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 16022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (withinFeatureGroup && tag == "uses-feature") { 1603d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup& top = featureGroups.editTop(); 1604d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 1605ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error); 1606d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (name != "" && error == "") { 1607d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski top.features.add(name, true); 1608d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski addParentFeatures(&top, name); 1609d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else { 1610ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR, 1611ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1612d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (error == "") { 1613d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > top.openGLESVersion) { 1614d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski top.openGLESVersion = vers; 1615d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1616d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 16172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1618a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 161994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 4) { 162094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "intent-filter") { 162194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasIntentFilter = true; 162294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinIntentFilter = true; 162394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actMainActivity = false; 162494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWidgetReceivers = false; 162594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actImeService = false; 162694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWallpaperService = false; 162794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actAccessibilityService = false; 162894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actPrintService = false; 162994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actDeviceAdminEnabled = false; 163094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = false; 163194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = false; 16329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = false; 16339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = false; 1634eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = false; 16359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = false; 16369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = false; 16379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = false; 163894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (withinService && tag == "meta-data") { 1639ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 164094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 164194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute for" 164294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 164394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 164494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 164594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 164694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service" || 164794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski name == "android.nfc.cardemulation.off_host_apdu_service") { 164894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool offHost = true; 164994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service") { 165094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost = false; 165194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 165294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 1653ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 xmlPath = AaptXml::getResolvedAttribute(res, tree, 1654ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski RESOURCE_ATTR, &error); 165594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 165694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:resource' attribute for" 165794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 165894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 165994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 166094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories = getNfcAidCategories(assets, xmlPath, 166294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost, &error); 166394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 166494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting AID category for service '%s'\n", 166594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski serviceName.string()); 166694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 166794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 166894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 166994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const size_t catLen = categories.size(); 167094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski for (size_t i = 0; i < catLen; i++) { 167194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool paymentCategory = (categories[i] == "payment"); 167294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (offHost) { 167394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory |= paymentCategory; 167494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 167594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory |= paymentCategory; 167694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 167794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 167894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 167994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1680a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if ((depth == 5) && withinIntentFilter) { 1681a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 action; 1682a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "action") { 1683ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski action = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1684a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1685a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1686a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1687a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1688a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1689a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1690a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1691a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.MAIN") { 1692a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isMainActivity = true; 1693a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actMainActivity = true; 16949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA" || 16959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski action == "android.media.action.VIDEO_CAMERA") { 16969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = true; 16979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") { 16989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = true; 1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1700a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinReceiver) { 1701a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 1702a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWidgetReceivers = true; 1703a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") { 1704a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actDeviceAdminEnabled = true; 1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1706a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinService) { 1707a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.view.InputMethod") { 1708a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actImeService = true; 1709a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.service.wallpaper.WallpaperService") { 1710a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWallpaperService = true; 1711a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.accessibilityservice.AccessibilityService") { 1712a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actAccessibilityService = true; 1713a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.printservice.PrintService") { 1714a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actPrintService = true; 171594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { 171694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = true; 171794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { 171894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = true; 17199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.service.notification.NotificationListenerService") { 17209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = true; 1721eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (action == "android.service.dreams.DreamService") { 1722eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = true; 17239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 17249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 17259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (action == "android.content.action.DOCUMENTS_PROVIDER") { 17269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = true; 1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1729a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.SEARCH") { 1730a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isSearchable = true; 1731a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1732a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1734a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "category") { 1735ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1736a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1737a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'name' attribute: %s\n", 1738a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1739a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1740a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1741a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1742a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (category == "android.intent.category.LAUNCHER") { 1743a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isLauncherActivity = true; 17440a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } else if (category == "android.intent.category.LEANBACK_LAUNCHER") { 17450a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isLeanbackLauncherActivity = true; 17469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (category == "android.intent.category.HOME") { 17479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = true; 1748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-1.6 implicitly granted permission compatibility logic 1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 4) { 1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteExternalStoragePermission) { 175758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE")); 175858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"), 175958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadPhoneStatePermission) { 176358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_PHONE_STATE")); 176458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"), 176558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the application has requested WRITE_EXTERNAL_STORAGE, we will 1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // force them to always take READ_EXTERNAL_STORAGE as well. We always 1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // do this (regardless of target API version) because we can't have 1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // an app with write permission but not read permission. 1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { 177458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE")); 177558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 177658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("requested WRITE_EXTERNAL_STORAGE")); 1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-JellyBean call log permission compatibility. 1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 16) { 1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadCallLogPermission && hasReadContactsPermission) { 178258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_CALL_LOG")); 178358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"), 178458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested READ_CONTACTS")); 1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteCallLogPermission && hasWriteContactsPermission) { 178758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_CALL_LOG")); 178858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"), 178958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested WRITE_CONTACTS")); 1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen", 17942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "default feature for all apps"); 17952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 17962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatureGroups = featureGroups.size(); 17972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (numFeatureGroups == 0) { 17982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // If no <feature-group> tags were defined, apply auto-implied features. 17992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(commonFeatures, &impliedFeatures); 18002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 18012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else { 18022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // <feature-group> tags are defined, so we ignore implied features and 18032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatureGroups; i++) { 18042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup& grp = featureGroups.editItemAt(i); 18052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1806d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (commonFeatures.openGLESVersion > grp.openGLESVersion) { 1807d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.openGLESVersion = commonFeatures.openGLESVersion; 1808d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1809d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 18102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // Merge the features defined in the top level (not inside a <feature-group>) 18112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // with this feature group. 18122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numCommonFeatures = commonFeatures.features.size(); 18132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numCommonFeatures; j++) { 18142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) { 1815d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.features.add(commonFeatures.features.keyAt(j), 1816d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.features[j]); 18172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features.isEmpty()) { 18212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(grp); 18222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWidgetReceivers) { 18289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("app-widget"); 1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasDeviceAdminReceiver) { 18319d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("device-admin"); 1832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasImeService) { 18349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("ime"); 1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWallpaperService) { 18379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("wallpaper"); 1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1839a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasAccessibilityService) { 18409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("accessibility"); 1841a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1842a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasPrintService) { 18439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("print-service"); 1844a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 184594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (hasPaymentService) { 18469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("payment"); 18479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (isSearchable) { 18499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("search"); 18509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasDocumentsProvider) { 18529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("document-provider"); 18539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasLauncher) { 18559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("launcher"); 18569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasNotificationListenerService) { 18589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("notification-listener"); 18599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 1860eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock if (hasDreamService) { 1861eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock printComponentPresence("dream"); 1862eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } 18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraActivity) { 18649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera"); 18659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraSecureActivity) { 18679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera-secure"); 18689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 18709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasMainActivity) { 18719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("main\n"); 187294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherActivities) { 1874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-activities\n"); 1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 18769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasOtherReceivers) { 1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-receivers\n"); 1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherServices) { 1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-services\n"); 1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For modern apps, if screen size buckets haven't been specified 1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but the new width ranges have, then infer the buckets from them. 1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && requiresSmallestWidthDp > 0) { 1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatWidth = compatibleWidthLimitDp; 1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatWidth <= 0) { 1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatWidth = requiresSmallestWidthDp; 1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { 1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = -1; 1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = 0; 1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { 1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = 0; 1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { 1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = -1; 1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = 0; 1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { 1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = -1; 1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = 0; 1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Determine default values for any unspecified screen sizes, 1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // based on the target SDK of the package. As of 4 (donut) 1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the screen size support was introduced, so all default to 1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // enabled. 1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0) { 1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = targetSdk >= 4 ? -1 : 0; 1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen > 0) { 1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen > 0) { 1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = targetSdk >= 4 ? -1 : 0; 1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen > 0) { 1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Introduced in Gingerbread. 1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = targetSdk >= 9 ? -1 : 0; 1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (anyDensity > 0) { 1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || compatibleWidthLimitDp > 0) ? -1 : 0; 1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-screens:"); 1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen != 0) { 1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'small'"); 1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen != 0) { 1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'normal'"); 1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen != 0) { 1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'large'"); 1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen != 0) { 1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'xlarge'"); 1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); 1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp > 0) { 1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); 1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatibleWidthLimitDp > 0) { 1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); 1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largestWidthLimitDp > 0) { 1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("largest-width-limit:'%d'\n", largestWidthLimitDp); 1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("locales:"); 1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localeStr = "--_--"; 1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'", localeStr); 1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("densities:"); 1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%d'", densities[i]); 1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir != NULL) { 1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir->getFileCount() > 0) { 1980e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski SortedVector<String8> architectures; 1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<dir->getFileCount(); i++) { 1982e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.add(ResTable::normalizeForOutput( 1983e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski dir->getFileName(i).string())); 1984e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1985e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1986e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool outputAltNativeCode = false; 1987e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // A multiArch package is one that contains 64-bit and 1988e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit versions of native code and expects 3rd-party 1989e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // apps to load these native code libraries. Since most 1990e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 64-bit systems also support 32-bit apps, the apps 1991e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // loading this multiArch package's code may be either 1992e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit or 64-bit. 1993e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (hasMultiArch) { 1994e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If this is a multiArch package, report the 64-bit 1995e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // version only. Then as a separate entry, report the 1996e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // rest. 1997e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 1998e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If we report the 32-bit architecture, this APK will 1999e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // be installed on a 32-bit device, causing a large waste 2000e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // of bandwidth and disk space. This assumes that 2001e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // the developer of the multiArch package has also 2002e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // made a version that is 32-bit only. 2003e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 intel64("x86_64"); 2004e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 arm64("arm64-v8a"); 2005e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski ssize_t index = architectures.indexOf(intel64); 2006e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index < 0) { 2007e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski index = architectures.indexOf(arm64); 2008e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2009e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2010e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index >= 0) { 2011e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code: '%s'\n", architectures[index].string()); 2012e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.removeAt(index); 2013e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski outputAltNativeCode = true; 2014e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2015e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2016e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2017e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski const size_t archCount = architectures.size(); 2018e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (archCount > 0) { 2019e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (outputAltNativeCode) { 2020e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("alt-"); 2021e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2022e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code:"); 2023e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski for (size_t i = 0; i < archCount; i++) { 2024e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf(" '%s'", architectures[i].string()); 2025e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2026e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("\n"); 2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete dir; 2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badger", option) == 0) { 2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s", CONSOLE_DATA); 2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("configurations", option) == 0) { 2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = configs.size(); 2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", configs[i].toString().string()); 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset) { 2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive. 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle) 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getUpdate()) { 2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* avoid confusion */ 2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: can't use '-u' with add\n"); 2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, true); 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'... (from gzip)\n", fileName); 2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getJunkPath()) { 2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 storageName = String8(fileName).getPathLeaf(); 20982675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s' as '%s'...\n", fileName, 20992675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(storageName.string()).string()); 2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, storageName.string(), 2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getCompressionMethod(), NULL); 2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'...\n", fileName); 2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": file not found\n"); 2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == ALREADY_EXISTS) { 2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": already exists in archive\n"); 2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "\n"); 2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive. 2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle) 2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, false); 2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName); 2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipEntry* entry; 2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByName(fileName); 2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry == NULL) { 2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s' NOT FOUND\n", fileName); 2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->remove(entry); 2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to delete '%s' from '%s'\n", 2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getFileSpecEntry(i), zipFileName); 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* update the archive */ 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->flush(); 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21823921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) { 2183fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numDirs = dir->getDirs().size(); 2184fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numDirs; i++) { 21853921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski bool ignore = ignoreConfig; 21863921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); 21873921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const char* dirStr = subDir->getLeaf().string(); 21883921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (!ignore && strstr(dirStr, "mipmap") == dirStr) { 21893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski ignore = true; 21903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 21913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = addResourcesToBuilder(subDir, builder, ignore); 2192fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2193fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2194fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2195fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2196fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2197fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numFiles = dir->getFiles().size(); 2198fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numFiles; i++) { 2199fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<AaptGroup> gp = dir->getFiles().valueAt(i); 2200fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numConfigs = gp->getFiles().size(); 2201fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t j = 0; j < numConfigs; j++) { 22023921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = NO_ERROR; 22033921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (ignoreConfig) { 22043921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22053921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } else { 22063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 2208fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2209fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Failed to add %s (%s) to builder.\n", 2210fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); 2211fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2212fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2213fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2214fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) { 2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (split->isBase()) { 2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return original; 2221fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2222fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2223fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 ext(original.getPathExtension()); 2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (ext == String8(".apk")) { 2225fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s%s", 2226fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski original.getBasePath().string(), 2227fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string(), 2228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ext.string()); 2229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s", original.string(), 2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string()); 2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files. 2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle) 2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* outputAPKFile; 2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retVal = 1; 2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptAssets> assets; 2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int N; 2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FILE* fp; 2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 dependencyFile; 2247fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<ApkBuilder> builder; 2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2249a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // -c en_XA or/and ar_XB means do pseudolocalization 2250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<WeakResourceFilter> configFilter = new WeakResourceFilter(); 2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = configFilter->parse(bundle->getConfigurations()); 2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudo()) { 2256a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); 2257a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 2258fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudoBidi()) { 2259a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); 2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = bundle->getFileSpecCount(); 2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 226409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { 2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no input files\n"); 2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile = bundle->getOutputAPKFile(); 2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure the filenames provided exist and are of the appropriate type. 2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FileType type; 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = getFileType(outputAPKFile); 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "ERROR: output file '%s' exists but is not regular file\n", 2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile); 2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Load the assets. 2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets = new AaptAssets(); 2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set up the resource gathering in assets if we're going to generate 2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dependency files. Every time we encounter a resource while slurping 2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the tree, we'll add it to these stores so we have full resource paths 2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to write to a dependency file. 2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> resPathStore = new FilePathStore; 2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullResPaths(resPathStore); 2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> assetPathStore = new FilePathStore; 2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullAssetPaths(assetPathStore); 2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = assets->slurpFromArgs(bundle); 2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->print(String8()); 2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2306fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Create the ApkBuilder, which will collect the compiled files 2307fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // to write to the final APK (or sets of APKs if we are building 2308fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // a Split APK. 2309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski builder = new ApkBuilder(configFilter); 2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If we are generating a Split APK, find out which configurations to split on. 2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (bundle->getSplitConfigurations().size() > 0) { 2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<String8>& splitStrs = bundle->getSplitConfigurations(); 2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splitStrs.size(); 2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::set<ConfigDescription> configs; 2317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) { 2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string()); 2319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = builder->createSplitForConfigs(configs); 2323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If they asked for any fileAs that need to be compiled, do so. 2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = buildResources(bundle, assets, builder); 2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != 0) { 2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At this point we've read everything and processed everything. From here 2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // on out it's just writing output files. 2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update symbols with information about which ones are needed as Java symbols. 2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->applyJavaSymbols(); 2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, do that here 2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is the packaging step, generate the dependency file next to 2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the output apk (e.g. bin/resources.ap_.d) 2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(outputAPKFile); 2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add the .d extension to the dependency file. 2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.append(".d"); 2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Else if this is the R.java dependency generation step, 2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // generate the dependency file in the R.java package subdirectory 2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java.d 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(bundle->getRClassDir()); 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.appendPath("R.java.d"); 2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure we have a clean dependency file to start with 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "w"); 2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out R.java constants 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets->havePrivateSymbols()) { 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getCustomPackage() == NULL) { 2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file into the appropriate class directory 2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java 23741e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), true, 23751e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski bundle->getBuildSharedLibrary()); 2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 customPkg(bundle->getCustomPackage()); 23781e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, customPkg, true, 23791e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski bundle->getBuildSharedLibrary()); 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we have library files, we're going to write our R.java file into 2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the appropriate class directory for those libraries as well. 2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/lib/R.java 2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getExtraPackages() != NULL) { 2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Split on colon 2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 libs(bundle->getExtraPackages()); 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (packageString != NULL) { 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file out with the correct package name 23931e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, String8(packageString), true, false); 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski packageString = strtok(NULL, ":"); 2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski libs.unlockBuffer(); 2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 24021e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false); 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 24061e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false); 2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out the ProGuard file 2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeProguardFile(bundle, assets); 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the apk 2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2420fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Gather all resources and add them to the APK Builder. The builder will then 2421fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // figure out which Split they belong in. 2422fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = addResourcesToBuilder(assets, builder); 2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<sp<ApkSplit> >& splits = builder->getSplits(); 2428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splits.size(); 2429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const sp<ApkSplit>& split = splits[i]; 2431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 outputPath = buildApkName(String8(outputAPKFile), split); 2432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = writeAPK(bundle, outputPath, split); 2433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string()); 2435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, we need to finish up here. 2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the writeResourceSymbols and writeAPK functions have already written the target 2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // half of the dependency file, now we need to write the prerequisites. (files that 2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the R.java file or .ap_ file depend on) 2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now that writeResourceSymbols or writeAPK has taken care of writing 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the targets to our dependency file, we'll write the prereqs 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "a+"); 2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " : "); 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool includeRaw = (outputAPKFile != NULL); 2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); 2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Also manually add the AndroidManifeset since it's not under res/ or assets/ 2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and therefore was not added to our pathstores during slurping 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retVal = 0; 2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos::printErrors(stderr); 2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return retVal; 2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching 2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -S flag points to a source directory containing drawable* folders 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -C flag points to destination directory. The folder structure in the 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * source directory will be mirrored to the destination (cache) directory 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Destination directory will be updated to match the PNG files in 24742675f769673f69b0661ddee346292f25cb30a296Maurice Chu * the source directory. 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle) 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching PNG Files in "); 2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski updatePreProcessedCache(bundle); 2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag 2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -i points to a single png file 2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -o points to a single png output file 2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle) 2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); 2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); 2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 input(bundle->getSingleCrunchInputFile()); 2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 output(bundle->getSingleCrunchOutputFile()); 2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { 2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we can't return the status_t as it gets truncate to the lower 8 bits. 2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 42; 2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = { 2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, 2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, 2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, 2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, 2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, 2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, 2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, 2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, 2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, 2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, 2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, 2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, 2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, 2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 2673