Command.cpp revision 25d35a9d68fed6304352d0bfc2e0d581ed47f8b5
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h" 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h" 82c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h" 92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h" 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h> 152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h> 162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h> 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h> 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h> 202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h> 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h> 232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h> 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info. All the cool kids do it. 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle) 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 0) { 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("(ignoring extra arguments)\n"); 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Android Asset Packaging Tool, v0.2\n"); 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only. The call fails if the file doesn't exist. 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName) 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip; 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, ZipFile::kOpenReadOnly); 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' not found\n", fileName); 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == PERMISSION_DENIED) { 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileName); 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write. The file will be created if it doesn't 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set. 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate) 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int flags; 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags = ZipFile::kOpenReadWrite; 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (okayToCreate) { 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags |= ZipFile::kOpenCreate; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, flags); 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = NULL; 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method. 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method) 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (method == ZipEntry::kCompressStored) { 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Stored"; 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (method == ZipEntry::kCompressDeflated) { 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Deflated"; 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Unknown"; 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression). 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen) 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!uncompressedLen) { 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing. 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip" 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command. 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle) 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ZipEntry* entry; 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long totalUncLen, totalCompLen; 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 1) { 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: specify zip file name (only)\n"); 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadOnly(zipFileName); 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int count, i; 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Archive: %s\n", zipFileName); 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen = totalCompLen = 0; 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski count = zip->getNumEntries(); 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i = 0; i < count; i++) { 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByIndex(i); 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char dateBuf[32]; 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time_t when; 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski when = entry->getModWhen(); 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localtime(&when)); 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getUncompressedLen(), 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compressionName(entry->getCompressionMethod()), 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getCompressedLen(), 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(entry->getUncompressedLen(), 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCompressedLen()), 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (size_t) entry->getLFHOffset(), 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dateBuf, 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCRC32(), 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getFileName()); 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", entry->getFileName()); 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen += entry->getUncompressedLen(); 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen += entry->getCompressedLen(); 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------- --- -------\n"); 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %7ld %2d%% %d files\n", 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen, 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen, 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(totalUncLen, totalCompLen), 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->getNumEntries()); 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getAndroidList()) { 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(zipFileName), NULL)) { 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo resource table found.\n"); 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nResource table:\n"); 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(false); 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t N = tree.getAttributeCount(); 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeNameResID(i) == attrRes) { 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (ssize_t)i; 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return -1; 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 getAttribute(const ResXMLTree& tree, const char* ns, 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* attr, String8* outError) 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = tree.indexOfAttribute(ns, attr); 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8* outError, int32_t defValue = -1) 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not an integer value"; 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree, 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrRes, String8* outError, int32_t defValue = -1) 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE) { 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(&value, 0); 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not an integer value"; 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree, 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrRes, String8* outError) 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType == Res_value::TYPE_STRING) { 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(&value, 0); 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Res_value* value2 = &value; 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len); 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable, 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResXMLTree& tree, uint32_t attrRes, String8* outError) 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute could not be found"; 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, value) != NO_ERROR) { 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value->dataType == Res_value::TYPE_REFERENCE) { 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(value, 0); 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // The attribute was found and was resolved if need be. 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "error getting resolved resource attribute"; 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38576327314d2238e105f8b94909f9c0cf85caca318Maurice Chustatic void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree, 38676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu uint32_t attrRes, String8 attrLabel, String8* outError) 38776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 38876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 38976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError); 39076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 39176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 39276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 39376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 39476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 39576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8 result = getResolvedAttribute(resTable, tree, attrRes, outError); 3962675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 3972675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 39876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 39976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 40076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 40176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 40276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 40376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 40476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 40576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 412a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 4139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 4149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 41594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 4440a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4472675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 4562675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4582675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4619cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 4799cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4809cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4819cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4829cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 4839cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4849cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t screenSize = getIntegerAttribute(tree, 487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR, NULL, -1); 488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t screenDensity = getIntegerAttribute(tree, 489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR, NULL, -1); 490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 50258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) { 50358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 50458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 50558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 50658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 50758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 50858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 50958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 51058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 51158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 51258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 51358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 51458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 51558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 51658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 51758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 51858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 51958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) { 52058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-implied-permission: name='%s' reason='%s'\n", 52158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string(), 52258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(reason.string()).string()); 52358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 52458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 52594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, 52694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 52794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 52894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 52994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 53094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 53194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 53294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 53394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 53594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 53794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 53894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 54094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 54194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 54294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 54394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 54494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 54594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 54694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 54794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 54894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 5499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 5509cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 5519cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 5529cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 5539cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 5549cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 55594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 55694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 55794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 55894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 55994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 56094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 56194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 5629cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 5639cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 5649cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 5659cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 5669cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 5679cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 56894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 56994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 57094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 57194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 57294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 57394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 57494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 57594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 category = getAttribute(tree, CATEGORY_ATTR, &error); 57694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 57794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 57894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 57994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 58194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 58294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 58794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 58894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 58994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 5909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 5919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 5929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 5939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 5942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 5952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to 5962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason. 5972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 5982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature { 5992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Name of the implied feature. 6012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name; 6032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * List of human-readable reasons for why this feature was implied. 6062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski SortedVector<String8> reasons; 6082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 6092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 6112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml 6122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup { 614d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup() : openGLESVersion(-1) {} 615d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 6162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Human readable label 6182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 label; 6202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Explicit features defined in the group 6232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, bool> features; 625d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 626d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski /** 627d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski * OpenGL ES version required 628d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski */ 629d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int openGLESVersion; 6302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 6312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures, 6332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const char* name, const char* reason) { 6342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name8(name); 6352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ssize_t idx = impliedFeatures->indexOfKey(name8); 6362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (idx < 0) { 6372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski idx = impliedFeatures->add(name8, ImpliedFeature()); 6382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).name = name8; 6392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).reasons.add(String8(reason)); 6412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 6422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp, 6442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) { 6452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("feature-group: label='%s'\n", grp.label.string()); 6462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 647d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (grp.openGLESVersion > 0) { 648d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski printf(" uses-gl-es: '0x%x'\n", grp.openGLESVersion); 649d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 650d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 6512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatures = grp.features.size(); 6522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatures; i++) { 6532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features[i]) { 6542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 6552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const String8& featureName = grp.features.keyAt(i); 6582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", 6592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ResTable::normalizeForOutput(featureName.string()).string()); 6602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numImpliedFeatures = 6632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski (impliedFeatures != NULL) ? impliedFeatures->size() : 0; 6642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numImpliedFeatures; i++) { 6652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i); 6662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(impliedFeature.name) >= 0) { 6672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // The feature is explicitly set, no need to use implied 6682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // definition. 6692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 6702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 printableFeatureName(ResTable::normalizeForOutput( 6732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeature.name.string())); 6742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", printableFeatureName.string()); 6752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-implied-feature: name='%s' reason='", 6762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printableFeatureName.string()); 6772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numReasons = impliedFeature.reasons.size(); 6782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numReasons; j++) { 6792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("%s", impliedFeature.reasons[j].string()); 6802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (j + 2 < numReasons) { 6812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", "); 6822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (j + 1 < numReasons) { 6832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", and "); 6842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("'\n"); 6872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 6892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) { 6912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (name == "android.hardware.camera.autofocus" || 6922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.camera.flash") { 6932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.camera"), true); 6942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.location.gps" || 6952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.location.network") { 6962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.location"), true); 6972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 6982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 6992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct") { 7002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen.multitouch"), true); 7012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 702d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else if (name == "android.hardware.opengles.aep") { 703d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski const int openGLESVersion31 = 0x00030001; 704d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (openGLESVersion31 > grp->openGLESVersion) { 705d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp->openGLESVersion = openGLESVersion31; 706d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 7072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 7082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 7092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 732f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 74491447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 755c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 76163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 76225e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (res.getError() != NO_ERROR) { 76325e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 76463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 76563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski } 76663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 76763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); 76863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski if (dynamicRefTable == NULL) { 76963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski fprintf(stderr, "ERROR: failed to find dynamic reference table for asset cookie %d\n", 77063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski assetsCookie); 77163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 77463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski Asset* asset = NULL; 77563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 79363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 79463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 82063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 83863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); 839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 84463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 8659cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 8669cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 8679cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 8689cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 8699cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 8709cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg = getAttribute(tree, NULL, "package", NULL); 8782675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "permission") { 880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 8862675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("permission: %s\n", 8872675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "uses-permission") { 889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 89558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 89658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0, 89758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1)); 898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 9230a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 926ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 9272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski bool withinFeatureGroup = false; 928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 9309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 9369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 9379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 940a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 941a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 943a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 94494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 9459d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 9469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 9479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 9489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 9499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 950eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 9519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 954a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 957a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 958a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 95994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 96094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 9619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 9629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 963eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 9649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 9659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 9669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 96794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 96894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 969a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 970a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 971a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 972a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 973a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 974a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 97694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 9779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 9789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 979eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 10002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 10240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 1027ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 10282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 10292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup commonFeatures; 10302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski Vector<FeatureGroup> featureGroups; 10312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, ImpliedFeature> impliedFeatures; 10322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 1037ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 1038ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 1039ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 1040ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 10412675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 10422675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 1043ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 1044ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 1045ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1046ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 1047ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1048ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1049ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.clear(); 1050ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1052ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = false; 10532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = false; 1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 3) { 10550a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (withinActivity && isMainActivity) { 10562675f769673f69b0661ddee346292f25cb30a296Maurice Chu String8 aName(getComponentName(pkg, activityName)); 10570a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLauncherActivity) { 10580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("launchable-activity:"); 10599eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 10609eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 10619eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 10620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 10630a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s'\n", 10649eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 10659eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string()); 10660a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 10670a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLeanbackLauncherActivity) { 10680a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("leanback-launchable-activity:"); 10699eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 10709eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 10719eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 10720a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 10730a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s' banner='%s'\n", 10749eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 10759eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string(), 10769eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityBanner.string()).string()); 1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasIntentFilter) { 1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherActivities |= withinActivity; 1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherReceivers |= withinReceiver; 1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherServices |= withinService; 108394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 108494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (withinService) { 108594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && 108694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 108794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && 108894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 108994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 10949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 10960a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; 1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 4) { 1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinIntentFilter) { 1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinActivity) { 1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMainActivity |= actMainActivity; 11019d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasLauncher |= catLauncher; 11029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraActivity |= actCamera; 11039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraSecureActivity |= actCameraSecure; 11049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; 1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinReceiver) { 1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWidgetReceivers |= actWidgetReceivers; 1107a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasDeviceAdminReceiver |= (actDeviceAdminEnabled && 1108a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission); 1109a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); 1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinService) { 1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasImeService |= actImeService; 1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWallpaperService |= actWallpaperService; 1113a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasAccessibilityService |= (actAccessibilityService && 1114a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission); 1115a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasPrintService |= (actPrintService && hasBindPrintServicePermission); 11169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasNotificationListenerService |= actNotificationListenerService && 11179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission; 1118eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasDreamService |= actDreamService && hasBindDreamServicePermission; 1119a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherServices |= (!actImeService && !actWallpaperService && 112094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski !actAccessibilityService && !actPrintService && 11219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actHostApduService && !actOffHostApduService && 11229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actNotificationListenerService); 11239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 11249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; 1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinIntentFilter = false; 1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 11359cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski 11369cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 11379cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 11389cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 11399cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 11409cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 11419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d, %s\n", depth, tag.string()); 1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pkg = getAttribute(tree, NULL, "package", NULL); 11492675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: name='%s' ", 11502675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(pkg.string()).string()); 1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error); 1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string()); 1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (versionCode > 0) { 1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='%d' ", versionCode); 1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='' "); 1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error); 1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 116625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("versionName='%s'", 11672675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(versionName.string()).string()); 116825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski 116925d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski String8 splitName = getAttribute(tree, NULL, "split", NULL); 117025d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski if (!splitName.isEmpty()) { 117125d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf(" split='%s'", ResTable::normalizeForOutput( 117225d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski splitName.string()).string()); 117325d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski } 117425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("\n"); 1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2) { 1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "application") { 1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = true; 1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 label; 1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setLocale(localeStr != NULL ? localeStr : ""); 1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (llabel != "") { 1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 11892675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-label:'%s'\n", 11902675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (label == "") { 1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-label-%s:'%s'\n", localeStr, 11962675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config tmpConfig = config; 1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tmpConfig.density = densities[i]; 1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(tmpConfig); 1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (icon != "") { 12082675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-icon-%d:'%s'\n", densities[i], 12092675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(icon.string()).string()); 1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); 1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0); 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string()); 1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 12242675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application: label='%s' ", 12252675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(label.string()).string()); 12262675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string()); 1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (testOnly != 0) { 1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("testOnly='%d'\n", testOnly); 1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0); 1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string()); 1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (debuggable != 0) { 1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-debuggable\n"); 1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-sdk") { 1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); 1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error); 1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", 1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut") targetSdk = 4; 12502675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("sdkVersion:'%s'\n", 12512675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("sdkVersion:'%d'\n", code); 1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1); 1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != -1) { 1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("maxSdkVersion:'%d'\n", code); 1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error); 1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", 1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut" && targetSdk < 4) targetSdk = 4; 12702675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("targetSdkVersion:'%s'\n", 12712675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < code) { 1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("targetSdkVersion:'%d'\n", code); 1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-configuration") { 1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqTouchScreen = getIntegerAttribute(tree, 1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR, NULL, 0); 1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqKeyboardType = getIntegerAttribute(tree, 1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR, NULL, 0); 1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqHardKeyboard = getIntegerAttribute(tree, 1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR, NULL, 0); 1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqNavigation = getIntegerAttribute(tree, 1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR, NULL, 0); 1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqFiveWayNav = getIntegerAttribute(tree, 1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR, NULL, 0); 1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-configuration:"); 1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqTouchScreen != 0) { 1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqTouchScreen='%d'", reqTouchScreen); 1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqKeyboardType != 0) { 1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqKeyboardType='%d'", reqKeyboardType); 1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqHardKeyboard != 0) { 1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqHardKeyboard='%d'", reqHardKeyboard); 1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqNavigation != 0) { 1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqNavigation='%d'", reqNavigation); 1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqFiveWayNav != 0) { 1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqFiveWayNav='%d'", reqFiveWayNav); 1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1306ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "supports-input") { 1307ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = true; 1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-screens") { 1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = getIntegerAttribute(tree, 1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR, NULL, 1); 1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = getIntegerAttribute(tree, 1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR, NULL, 1); 1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = getIntegerAttribute(tree, 1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR, NULL, 1); 1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = getIntegerAttribute(tree, 1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR, NULL, 1); 1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = getIntegerAttribute(tree, 1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR, NULL, 1); 1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski requiresSmallestWidthDp = getIntegerAttribute(tree, 1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0); 1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatibleWidthLimitDp = getIntegerAttribute(tree, 1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0); 1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largestWidthLimitDp = getIntegerAttribute(tree, 1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0); 13252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (tag == "feature-group") { 13262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = true; 13272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup group; 13282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski group.label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 13292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (error != "") { 13302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski fprintf(stderr, "ERROR getting 'android:label' attribute:" 13312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski " %s\n", error.string()); 13322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski goto bail; 13332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 13342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski featureGroups.add(group); 13352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-feature") { 1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int req = getIntegerAttribute(tree, 1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR, NULL, 1); 1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 13422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski commonFeatures.features.add(name, req); 13432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (req) { 13442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addParentFeatures(&commonFeatures, name); 1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int vers = getIntegerAttribute(tree, 1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR, &error); 1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error == "") { 1350d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > commonFeatures.openGLESVersion) { 1351d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.openGLESVersion = vers; 1352d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-permission") { 1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "android.permission.CAMERA") { 1359d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.camera", 13602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_FINE_LOCATION") { 13632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.gps", 13642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 13662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { 13702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { 13742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.network", 13752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 13772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || 1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.INSTALL_LOCATION_PROVIDER") { 13822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.BLUETOOTH" || 1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.BLUETOOTH_ADMIN") { 13872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (targetSdk > 4) { 13882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 13892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 13912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 13922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "targetSdkVersion > 4"); 13932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.RECORD_AUDIO") { 13952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.microphone", 13962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_WIFI_STATE" || 1399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_STATE" || 1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { 14012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.wifi", 14022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.CALL_PHONE" || 1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CALL_PRIVILEGED" || 1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.MODIFY_PHONE_STATE" || 1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.PROCESS_OUTGOING_CALLS" || 1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.READ_SMS" || 1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_SMS" || 1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_MMS" || 1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_WAP_PUSH" || 1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.SEND_SMS" || 1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_APN_SETTINGS" || 1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_SMS") { 14152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.telephony", 14162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8("requested a telephony permission").string()); 1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { 1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { 1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadExternalStoragePermission = true; 1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_PHONE_STATE") { 1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadPhoneStatePermission = true; 1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CONTACTS") { 1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadContactsPermission = true; 1425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CONTACTS") { 1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteContactsPermission = true; 1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CALL_LOG") { 1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadCallLogPermission = true; 1429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CALL_LOG") { 1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteCallLogPermission = true; 1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 143258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 143358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 143458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0, 143558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1)); 143658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } else { 1437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-package") { 1442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 14442675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("uses-package:'%s'\n", 14452675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "original-package") { 1452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 14542675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("original-package:'%s'\n", 14552675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-gl-texture") { 1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 14642675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("supports-gl-texture:'%s'\n", 14652675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "compatible-screens") { 14729cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski printCompatibleScreens(tree, &error); 14739cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (error != "") { 14749cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR getting compatible screens: %s\n", 14759cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski error.string()); 14769cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 14779cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "package-verifier") { 1480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error); 1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (publicKey != "" && error == "") { 1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("package-verifier: name='%s' publicKey='%s'\n", 14852675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string(), 14862675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(publicKey.string()).string()); 1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1490ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (depth == 3) { 1491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 14949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 149694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory = false; 149794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory = false; 149894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindDeviceAdminPermission = false; 149994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindInputMethodPermission = false; 150094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindAccessibilityServicePermission = false; 150194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindPrintServicePermission = false; 150294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = false; 15039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes = false; 15049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = false; 1505eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = false; 1506ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinApplication) { 1507ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if(tag == "activity") { 1508ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinActivity = true; 1509ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityName = getAttribute(tree, NAME_ATTR, &error); 1510ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1511ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1512ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1513ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1514ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1516ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 1517ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1518ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", 1519ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1520ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1521ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1523ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1524ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1525ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1526ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1527ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1528ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 15300a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error); 15310a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (error != "") { 15320a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", 15330a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn error.string()); 15340a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn goto bail; 15350a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 15360a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn 1537ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright int32_t orien = getResolvedIntegerAttribute(&res, tree, 1538ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright SCREEN_ORIENTATION_ATTR, &error); 1539ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error == "") { 1540ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (orien == 0 || orien == 6 || orien == 8) { 1541ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests landscape, sensorLandscape, or reverseLandscape. 15422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape", 15432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a landscape orientation"); 1544ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (orien == 1 || orien == 7 || orien == 9) { 1545ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests portrait, sensorPortrait, or reversePortrait. 15462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait", 15472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a portrait orientation"); 1548ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1550ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "uses-library") { 1551ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright String8 libraryName = getAttribute(tree, NAME_ATTR, &error); 1552ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1553ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1554ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for uses-library" 1555ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1556ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1557ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1558ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright int req = getIntegerAttribute(tree, 1559ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright REQUIRED_ATTR, NULL, 1); 1560ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("uses-library%s:'%s'\n", 15612675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", ResTable::normalizeForOutput( 15622675f769673f69b0661ddee346292f25cb30a296Maurice Chu libraryName.string()).string()); 1563ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "receiver") { 1564ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinReceiver = true; 1565ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright receiverName = getAttribute(tree, NAME_ATTR, &error); 1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1567ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1568ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1569ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for receiver:" 1570ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1571ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1572ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1573a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1574a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 permission = getAttribute(tree, PERMISSION_ATTR, &error); 1575a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1576a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_DEVICE_ADMIN") { 1577a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission = true; 1578a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1579a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1580a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1581a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " receiver '%s': %s\n", receiverName.string(), error.string()); 1582a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1583ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "service") { 1584ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinService = true; 1585ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright serviceName = getAttribute(tree, NAME_ATTR, &error); 1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1587ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1588ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1589ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "service:%s\n", error.string()); 1590ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1591ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1592a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1593a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 permission = getAttribute(tree, PERMISSION_ATTR, &error); 1594a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1595a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_INPUT_METHOD") { 1596a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindInputMethodPermission = true; 1597a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") { 1598a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission = true; 1599a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_PRINT_SERVICE") { 1600a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindPrintServicePermission = true; 160194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (permission == "android.permission.BIND_NFC_SERVICE") { 160294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = true; 16039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { 16049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = true; 1605eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (permission == "android.permission.BIND_DREAM_SERVICE") { 1606eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = true; 1607a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1608a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1609a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1610a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " service '%s': %s\n", serviceName.string(), error.string()); 1611a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 16129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (tag == "provider") { 16139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = true; 16149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error); 16169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 16179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:" 16189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 16199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 16209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree, 16239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR, &error); 16249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 16259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:" 16269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 16279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 16289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error); 16319d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 16329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:" 16339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 16349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 16359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes |= exported && grantUriPermissions && 16389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski permission == "android.permission.MANAGE_DOCUMENTS"; 16399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1640ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (bundle->getIncludeMetaData() && tag == "meta-data") { 1641b71adb6571aa740f4fa794602133f708e1b96545Adam Lesinski String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error); 1642ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1643ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1644ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "meta-data:%s\n", error.string()); 1645ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1646ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 16472675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("meta-data: name='%s' ", 16482675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(metaDataName.string()).string()); 164976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"), 165076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu &error); 1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 165276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu // Try looking for a RESOURCE_ATTR 165376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu error = ""; 165476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR, 165576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8("resource"), &error); 1656ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 165776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu fprintf(stderr, "ERROR getting 'android:value' or " 165876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "'android:resource' attribute for " 165976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "meta-data:%s\n", error.string()); 1660ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1661ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1662ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 166376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("\n"); 1664ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (withinSupportsInput && tag == "input-type") { 1665ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright String8 name = getAttribute(tree, NAME_ATTR, &error); 1666ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (name != "" && error == "") { 1667ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.add(name); 1668ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1669ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1670ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 16742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (withinFeatureGroup && tag == "uses-feature") { 1675d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup& top = featureGroups.editTop(); 1676d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 16772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name = getResolvedAttribute(&res, tree, NAME_ATTR, &error); 1678d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (name != "" && error == "") { 1679d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int required = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1); 1680d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski top.features.add(name, required); 1681d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (required) { 1682d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski addParentFeatures(&top, name); 1683d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 16842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1685d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else { 1686d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int vers = getIntegerAttribute(tree, GL_ES_VERSION_ATTR, &error); 1687d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (error == "") { 1688d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > top.openGLESVersion) { 1689d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski top.openGLESVersion = vers; 1690d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1691d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 16922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1693a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 169494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 4) { 169594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "intent-filter") { 169694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasIntentFilter = true; 169794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinIntentFilter = true; 169894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actMainActivity = false; 169994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWidgetReceivers = false; 170094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actImeService = false; 170194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWallpaperService = false; 170294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actAccessibilityService = false; 170394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actPrintService = false; 170494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actDeviceAdminEnabled = false; 170594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = false; 170694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = false; 17079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = false; 17089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = false; 1709eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = false; 17109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = false; 17119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = false; 17129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = false; 171394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (withinService && tag == "meta-data") { 171494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 171594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 171694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute for" 171794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 171894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 171994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 172094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 172194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service" || 172294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski name == "android.nfc.cardemulation.off_host_apdu_service") { 172394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool offHost = true; 172494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service") { 172594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost = false; 172694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 172794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 172894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error); 172994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 173094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:resource' attribute for" 173194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 173294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 173394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 173494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 173594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories = getNfcAidCategories(assets, xmlPath, 173694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost, &error); 173794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 173894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting AID category for service '%s'\n", 173994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski serviceName.string()); 174094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 174194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 174294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 174394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const size_t catLen = categories.size(); 174494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski for (size_t i = 0; i < catLen; i++) { 174594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool paymentCategory = (categories[i] == "payment"); 174694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (offHost) { 174794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory |= paymentCategory; 174894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 174994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory |= paymentCategory; 175094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 175194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 175294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 175394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1754a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if ((depth == 5) && withinIntentFilter) { 1755a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 action; 1756a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "action") { 1757a5018c900f126ee8424c82497f32983873db741bAdam Lesinski action = getAttribute(tree, NAME_ATTR, &error); 1758a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1759a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1760a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1761a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1762a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1763a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1764a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1765a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.MAIN") { 1766a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isMainActivity = true; 1767a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actMainActivity = true; 17689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA" || 17699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski action == "android.media.action.VIDEO_CAMERA") { 17709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = true; 17719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") { 17729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = true; 1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1774a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinReceiver) { 1775a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 1776a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWidgetReceivers = true; 1777a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") { 1778a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actDeviceAdminEnabled = true; 1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1780a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinService) { 1781a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.view.InputMethod") { 1782a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actImeService = true; 1783a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.service.wallpaper.WallpaperService") { 1784a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWallpaperService = true; 1785a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.accessibilityservice.AccessibilityService") { 1786a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actAccessibilityService = true; 1787a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.printservice.PrintService") { 1788a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actPrintService = true; 178994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { 179094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = true; 179194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { 179294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = true; 17939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.service.notification.NotificationListenerService") { 17949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = true; 1795eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (action == "android.service.dreams.DreamService") { 1796eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = true; 17979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 17989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 17999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (action == "android.content.action.DOCUMENTS_PROVIDER") { 18009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = true; 1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1803a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.SEARCH") { 1804a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isSearchable = true; 1805a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1806a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1808a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "category") { 1809a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 category = getAttribute(tree, NAME_ATTR, &error); 1810a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1811a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'name' attribute: %s\n", 1812a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1813a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1814a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1815a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1816a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (category == "android.intent.category.LAUNCHER") { 1817a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isLauncherActivity = true; 18180a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } else if (category == "android.intent.category.LEANBACK_LAUNCHER") { 18190a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isLeanbackLauncherActivity = true; 18209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (category == "android.intent.category.HOME") { 18219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = true; 1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-1.6 implicitly granted permission compatibility logic 1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 4) { 1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteExternalStoragePermission) { 183158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE")); 183258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"), 183358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadPhoneStatePermission) { 183758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_PHONE_STATE")); 183858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"), 183958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the application has requested WRITE_EXTERNAL_STORAGE, we will 1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // force them to always take READ_EXTERNAL_STORAGE as well. We always 1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // do this (regardless of target API version) because we can't have 1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // an app with write permission but not read permission. 1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { 184858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE")); 184958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 185058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("requested WRITE_EXTERNAL_STORAGE")); 1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-JellyBean call log permission compatibility. 1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 16) { 1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadCallLogPermission && hasReadContactsPermission) { 185658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_CALL_LOG")); 185758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"), 185858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested READ_CONTACTS")); 1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteCallLogPermission && hasWriteContactsPermission) { 186158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_CALL_LOG")); 186258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"), 186358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested WRITE_CONTACTS")); 1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen", 18682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "default feature for all apps"); 18692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 18702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatureGroups = featureGroups.size(); 18712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (numFeatureGroups == 0) { 18722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // If no <feature-group> tags were defined, apply auto-implied features. 18732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(commonFeatures, &impliedFeatures); 18742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 18752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else { 18762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // <feature-group> tags are defined, so we ignore implied features and 18772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatureGroups; i++) { 18782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup& grp = featureGroups.editItemAt(i); 18792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1880d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (commonFeatures.openGLESVersion > grp.openGLESVersion) { 1881d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.openGLESVersion = commonFeatures.openGLESVersion; 1882d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1883d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 18842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // Merge the features defined in the top level (not inside a <feature-group>) 18852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // with this feature group. 18862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numCommonFeatures = commonFeatures.features.size(); 18872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numCommonFeatures; j++) { 18882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) { 1889d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.features.add(commonFeatures.features.keyAt(j), 1890d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.features[j]); 18912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features.isEmpty()) { 18952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(grp); 18962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWidgetReceivers) { 19029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("app-widget"); 1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1904a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasDeviceAdminReceiver) { 19059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("device-admin"); 1906a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasImeService) { 19089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("ime"); 1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWallpaperService) { 19119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("wallpaper"); 1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1913a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasAccessibilityService) { 19149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("accessibility"); 1915a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1916a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasPrintService) { 19179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("print-service"); 1918a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 191994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (hasPaymentService) { 19209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("payment"); 19219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (isSearchable) { 19239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("search"); 19249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasDocumentsProvider) { 19269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("document-provider"); 19279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasLauncher) { 19299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("launcher"); 19309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19319d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasNotificationListenerService) { 19329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("notification-listener"); 19339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 1934eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock if (hasDreamService) { 1935eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock printComponentPresence("dream"); 1936eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } 19379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraActivity) { 19389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera"); 19399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraSecureActivity) { 19419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera-secure"); 19429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 19449d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasMainActivity) { 19459d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("main\n"); 194694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherActivities) { 1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-activities\n"); 1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 19509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasOtherReceivers) { 1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-receivers\n"); 1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherServices) { 1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-services\n"); 1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For modern apps, if screen size buckets haven't been specified 1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but the new width ranges have, then infer the buckets from them. 1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && requiresSmallestWidthDp > 0) { 1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatWidth = compatibleWidthLimitDp; 1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatWidth <= 0) { 1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatWidth = requiresSmallestWidthDp; 1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { 1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = -1; 1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = 0; 1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { 1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = 0; 1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { 1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = -1; 1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = 0; 1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { 1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = -1; 1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = 0; 1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Determine default values for any unspecified screen sizes, 1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // based on the target SDK of the package. As of 4 (donut) 1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the screen size support was introduced, so all default to 1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // enabled. 1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0) { 1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = targetSdk >= 4 ? -1 : 0; 1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen > 0) { 1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen > 0) { 1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = targetSdk >= 4 ? -1 : 0; 1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen > 0) { 2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Introduced in Gingerbread. 2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = targetSdk >= 9 ? -1 : 0; 2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (anyDensity > 0) { 2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || compatibleWidthLimitDp > 0) ? -1 : 0; 2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-screens:"); 2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen != 0) { 2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'small'"); 2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen != 0) { 2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'normal'"); 2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen != 0) { 2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'large'"); 2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen != 0) { 2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'xlarge'"); 2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); 2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp > 0) { 2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); 2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatibleWidthLimitDp > 0) { 2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); 2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largestWidthLimitDp > 0) { 2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("largest-width-limit:'%d'\n", largestWidthLimitDp); 2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("locales:"); 2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localeStr = "--_--"; 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'", localeStr); 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("densities:"); 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%d'", densities[i]); 2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir != NULL) { 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir->getFileCount() > 0) { 2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("native-code:"); 2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<dir->getFileCount(); i++) { 20562675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s'", ResTable::normalizeForOutput( 20572675f769673f69b0661ddee346292f25cb30a296Maurice Chu dir->getFileName(i).string()).string()); 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete dir; 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badger", option) == 0) { 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s", CONSOLE_DATA); 2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("configurations", option) == 0) { 2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = configs.size(); 2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", configs[i].toString().string()); 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset) { 2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or 2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive. 2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle) 2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getUpdate()) { 2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* avoid confusion */ 2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: can't use '-u' with add\n"); 2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, true); 2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'... (from gzip)\n", fileName); 2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getJunkPath()) { 2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 storageName = String8(fileName).getPathLeaf(); 21302675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s' as '%s'...\n", fileName, 21312675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(storageName.string()).string()); 2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, storageName.string(), 2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getCompressionMethod(), NULL); 2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'...\n", fileName); 2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": file not found\n"); 2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == ALREADY_EXISTS) { 2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": already exists in archive\n"); 2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "\n"); 2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive. 2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle) 2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, false); 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName); 2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipEntry* entry; 2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByName(fileName); 2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry == NULL) { 2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s' NOT FOUND\n", fileName); 2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->remove(entry); 2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to delete '%s' from '%s'\n", 2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getFileSpecEntry(i), zipFileName); 2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* update the archive */ 2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->flush(); 2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22143921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) { 2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numDirs = dir->getDirs().size(); 2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numDirs; i++) { 22173921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski bool ignore = ignoreConfig; 22183921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); 22193921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const char* dirStr = subDir->getLeaf().string(); 22203921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (!ignore && strstr(dirStr, "mipmap") == dirStr) { 22213921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski ignore = true; 22223921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 22233921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = addResourcesToBuilder(subDir, builder, ignore); 2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2225fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2226fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2227fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numFiles = dir->getFiles().size(); 2230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numFiles; i++) { 2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<AaptGroup> gp = dir->getFiles().valueAt(i); 2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numConfigs = gp->getFiles().size(); 2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t j = 0; j < numConfigs; j++) { 22343921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = NO_ERROR; 22353921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (ignoreConfig) { 22363921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22373921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } else { 22383921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22393921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 2240fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2241fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Failed to add %s (%s) to builder.\n", 2242fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); 2243fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2244fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2245fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2246fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2247fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 2248fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2249fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) { 2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (split->isBase()) { 2252fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return original; 2253fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2254fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 ext(original.getPathExtension()); 2256fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (ext == String8(".apk")) { 2257fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s%s", 2258fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski original.getBasePath().string(), 2259fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string(), 2260fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ext.string()); 2261fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2262fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2263fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s", original.string(), 2264fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string()); 2265fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files. 2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle) 2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* outputAPKFile; 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retVal = 1; 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptAssets> assets; 2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int N; 2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FILE* fp; 2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 dependencyFile; 2279fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<ApkBuilder> builder; 2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2281a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // -c en_XA or/and ar_XB means do pseudolocalization 2282fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<WeakResourceFilter> configFilter = new WeakResourceFilter(); 2283fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = configFilter->parse(bundle->getConfigurations()); 2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2287fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudo()) { 2288a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); 2289a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 2290fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudoBidi()) { 2291a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); 2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = bundle->getFileSpecCount(); 2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 229609384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { 2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no input files\n"); 2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile = bundle->getOutputAPKFile(); 2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure the filenames provided exist and are of the appropriate type. 2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FileType type; 2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = getFileType(outputAPKFile); 2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "ERROR: output file '%s' exists but is not regular file\n", 2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile); 2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Load the assets. 2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets = new AaptAssets(); 2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set up the resource gathering in assets if we're going to generate 2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dependency files. Every time we encounter a resource while slurping 2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the tree, we'll add it to these stores so we have full resource paths 2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to write to a dependency file. 2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> resPathStore = new FilePathStore; 2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullResPaths(resPathStore); 2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> assetPathStore = new FilePathStore; 2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullAssetPaths(assetPathStore); 2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = assets->slurpFromArgs(bundle); 2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->print(String8()); 2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2338fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Create the ApkBuilder, which will collect the compiled files 2339fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // to write to the final APK (or sets of APKs if we are building 2340fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // a Split APK. 2341fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski builder = new ApkBuilder(configFilter); 2342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If we are generating a Split APK, find out which configurations to split on. 2344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (bundle->getSplitConfigurations().size() > 0) { 2345fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<String8>& splitStrs = bundle->getSplitConfigurations(); 2346fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splitStrs.size(); 2347fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2348fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::set<ConfigDescription> configs; 2349fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) { 2350fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string()); 2351fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2352fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2353fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2354fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = builder->createSplitForConfigs(configs); 2355fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2356fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2357fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2358fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2359fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2360fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If they asked for any fileAs that need to be compiled, do so. 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 2363fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = buildResources(bundle, assets, builder); 2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != 0) { 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At this point we've read everything and processed everything. From here 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // on out it's just writing output files. 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update symbols with information about which ones are needed as Java symbols. 2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->applyJavaSymbols(); 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, do that here 2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is the packaging step, generate the dependency file next to 2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the output apk (e.g. bin/resources.ap_.d) 2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(outputAPKFile); 2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add the .d extension to the dependency file. 2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.append(".d"); 2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Else if this is the R.java dependency generation step, 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // generate the dependency file in the R.java package subdirectory 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java.d 2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(bundle->getRClassDir()); 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.appendPath("R.java.d"); 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure we have a clean dependency file to start with 2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "w"); 2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out R.java constants 2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets->havePrivateSymbols()) { 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getCustomPackage() == NULL) { 2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file into the appropriate class directory 2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java 2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), true); 2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 customPkg(bundle->getCustomPackage()); 2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, customPkg, true); 2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we have library files, we're going to write our R.java file into 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the appropriate class directory for those libraries as well. 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/lib/R.java 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getExtraPackages() != NULL) { 2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Split on colon 2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 libs(bundle->getExtraPackages()); 2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); 2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (packageString != NULL) { 2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file out with the correct package name 2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, String8(packageString), true); 2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski packageString = strtok(NULL, ":"); 2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski libs.unlockBuffer(); 2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), false); 2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true); 2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out the ProGuard file 2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeProguardFile(bundle, assets); 2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the apk 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2450fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Gather all resources and add them to the APK Builder. The builder will then 2451fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // figure out which Split they belong in. 2452fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = addResourcesToBuilder(assets, builder); 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2456fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2457fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<sp<ApkSplit> >& splits = builder->getSplits(); 2458fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splits.size(); 2459fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2460fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const sp<ApkSplit>& split = splits[i]; 2461fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 outputPath = buildApkName(String8(outputAPKFile), split); 2462fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = writeAPK(bundle, outputPath, split); 2463fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2464fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string()); 2465fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2466fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2467fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, we need to finish up here. 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the writeResourceSymbols and writeAPK functions have already written the target 2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // half of the dependency file, now we need to write the prerequisites. (files that 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the R.java file or .ap_ file depend on) 2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now that writeResourceSymbols or writeAPK has taken care of writing 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the targets to our dependency file, we'll write the prereqs 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "a+"); 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " : "); 2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool includeRaw = (outputAPKFile != NULL); 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Also manually add the AndroidManifeset since it's not under res/ or assets/ 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and therefore was not added to our pathstores during slurping 2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); 2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retVal = 0; 2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos::printErrors(stderr); 2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return retVal; 2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching 2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS 2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -S flag points to a source directory containing drawable* folders 2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -C flag points to destination directory. The folder structure in the 2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * source directory will be mirrored to the destination (cache) directory 2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS 2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Destination directory will be updated to match the PNG files in 25042675f769673f69b0661ddee346292f25cb30a296Maurice Chu * the source directory. 2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle) 2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching PNG Files in "); 2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); 2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); 2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski updatePreProcessedCache(bundle); 2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag 2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -i points to a single png file 2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -o points to a single png output file 2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle) 2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); 2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); 2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 input(bundle->getSingleCrunchInputFile()); 2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 output(bundle->getSingleCrunchOutputFile()); 2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { 2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we can't return the status_t as it gets truncate to the lower 8 bits. 2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 42; 2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = { 2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, 2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, 2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, 2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, 2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, 2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, 2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, 2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, 2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, 2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, 2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, 2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, 2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, 2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 2703