Command.cpp revision eb8d1be6acad180eabde84f19196b9ecaba81353
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 "Main.h" 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h" 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Images.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h> 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/List.h> 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Errors.h> 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <fcntl.h> 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h> 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info. All the cool kids do it. 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle) 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 0) { 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("(ignoring extra arguments)\n"); 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Android Asset Packaging Tool, v0.2\n"); 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only. The call fails if the file doesn't exist. 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName) 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip; 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, ZipFile::kOpenReadOnly); 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' not found\n", fileName); 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == PERMISSION_DENIED) { 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileName); 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write. The file will be created if it doesn't 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set. 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate) 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int flags; 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags = ZipFile::kOpenReadWrite; 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (okayToCreate) { 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags |= ZipFile::kOpenCreate; 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, flags); 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = NULL; 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method. 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method) 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (method == ZipEntry::kCompressStored) { 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Stored"; 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (method == ZipEntry::kCompressDeflated) { 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Deflated"; 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Unknown"; 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression). 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen) 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!uncompressedLen) { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing. 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip" 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command. 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle) 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ZipEntry* entry; 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long totalUncLen, totalCompLen; 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 1) { 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: specify zip file name (only)\n"); 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadOnly(zipFileName); 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int count, i; 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Archive: %s\n", zipFileName); 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen = totalCompLen = 0; 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski count = zip->getNumEntries(); 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i = 0; i < count; i++) { 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByIndex(i); 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char dateBuf[32]; 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time_t when; 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski when = entry->getModWhen(); 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localtime(&when)); 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getUncompressedLen(), 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compressionName(entry->getCompressionMethod()), 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getCompressedLen(), 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(entry->getUncompressedLen(), 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCompressedLen()), 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (size_t) entry->getLFHOffset(), 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dateBuf, 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCRC32(), 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getFileName()); 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", entry->getFileName()); 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen += entry->getUncompressedLen(); 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen += entry->getCompressedLen(); 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------- --- -------\n"); 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %7ld %2d%% %d files\n", 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen, 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen, 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(totalUncLen, totalCompLen), 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->getNumEntries()); 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getAndroidList()) { 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(zipFileName), NULL)) { 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo resource table found.\n"); 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nResource table:\n"); 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(false); 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t N = tree.getAttributeCount(); 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeNameResID(i) == attrRes) { 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (ssize_t)i; 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return -1; 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 getAttribute(const ResXMLTree& tree, const char* ns, 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* attr, String8* outError) 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = tree.indexOfAttribute(ns, attr); 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8* outError, int32_t defValue = -1) 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not an integer value"; 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree, 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrRes, String8* outError, int32_t defValue = -1) 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE) { 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(&value, 0); 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not an integer value"; 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree, 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrRes, String8* outError) 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType == Res_value::TYPE_STRING) { 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(&value, 0); 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Res_value* value2 = &value; 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len); 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable, 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResXMLTree& tree, uint32_t attrRes, String8* outError) 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute could not be found"; 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, value) != NO_ERROR) { 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value->dataType == Res_value::TYPE_REFERENCE) { 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(value, 0); 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // The attribute was found and was resolved if need be. 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "error getting resolved resource attribute"; 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38276327314d2238e105f8b94909f9c0cf85caca318Maurice Chustatic void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree, 38376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu uint32_t attrRes, String8 attrLabel, String8* outError) 38476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 38576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 38676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError); 38776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 38876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 38976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 39076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 39176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 39276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8 result = getResolvedAttribute(resTable, tree, attrRes, outError); 3932675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 3942675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 39576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 39676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 39776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 39876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 39976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 40076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 40176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 40276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 409a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 4109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 4119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 41294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 44094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 4410a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4442675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 4532675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4552675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4589cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 4769cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4779cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4789cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4799cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 4809cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4819cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t screenSize = getIntegerAttribute(tree, 484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR, NULL, -1); 485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t screenDensity = getIntegerAttribute(tree, 486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR, NULL, -1); 487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 49958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) { 50058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 50158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 50258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 50358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 50458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 50558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 50658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 50758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 50858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 50958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 51058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 51158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 51258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 51358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 51458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 51558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 51658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) { 51758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-implied-permission: name='%s' reason='%s'\n", 51858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string(), 51958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(reason.string()).string()); 52058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 52158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 52294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, 52394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 52494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 52594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 52694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 52794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 52894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 52994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 53094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 53294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 53494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 53594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 53794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 53894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 53994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 54094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 54194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 54294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 54394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 54494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 54594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 5469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 5479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 5489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 5499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 5509cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 5519cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 55294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 55394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 55494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 55594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 55694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 55794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 55894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 5599cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 5609cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 5619cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 5629cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 5639cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 5649cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 56594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 56694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 56794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 56894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 56994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 57094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 57194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 57294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 category = getAttribute(tree, CATEGORY_ATTR, &error); 57394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 57494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 57594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 57694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 57794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 57894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 57994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 58494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 58594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 58694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 5879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 5889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 5899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 5909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* asset = NULL; 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 614f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 62691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 64325e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (res.getError() != NO_ERROR) { 64425e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 64525e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski goto bail; 646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER); 667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER); 694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = assets.openNonAsset("AndroidManifest.xml", 712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 7389cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 7399cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 7409cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 7419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 7429cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 7439cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg = getAttribute(tree, NULL, "package", NULL); 7512675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "permission") { 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 7592675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("permission: %s\n", 7602675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "uses-permission") { 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 76858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 76958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0, 77058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1)); 771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 7960a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 799ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 8029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 8089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 812a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 813a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 815a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 81694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 8179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 8189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 8199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 8209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 8219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 822eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 826a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 829a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 83194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 83294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 8339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 8349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 835eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 8369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 8379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 8389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 83994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 84094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 841a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 842a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 843a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 844a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 845a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 846a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 847a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 84894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 8499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 8509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 851eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specCameraFeature = false; // camera-related 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specCameraAutofocusFeature = false; 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqCameraAutofocusFeature = false; 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqCameraFlashFeature = false; 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasCameraPermission = false; 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specLocationFeature = false; // location-related 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specNetworkLocFeature = false; 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqNetworkLocFeature = false; 880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specGpsFeature = false; 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqGpsFeature = false; 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMockLocPermission = false; 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasCoarseLocPermission = false; 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasGpsPermission = false; 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasGeneralLocPermission = false; 886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specBluetoothFeature = false; // Bluetooth API-related 887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasBluetoothPermission = false; 888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specMicrophoneFeature = false; // microphone-related 889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasRecordAudioPermission = false; 890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specWiFiFeature = false; 891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWiFiPermission = false; 892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specTelephonyFeature = false; // telephony-related 893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqTelephonySubFeature = false; 894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasTelephonyPermission = false; 895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specTouchscreenFeature = false; // touchscreen-related 896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specMultitouchFeature = false; 897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqDistinctMultitouchFeature = false; 898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specScreenPortraitFeature = false; 899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool specScreenLandscapeFeature = false; 900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqScreenPortraitFeature = false; 901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool reqScreenLandscapeFeature = false; 902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 9250a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 928ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 933ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 934ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 935ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 936ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 9372675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 9382675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 939ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 940ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 941ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 942ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 943ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 944ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 945ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.clear(); 946ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 948ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = false; 949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 3) { 9500a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (withinActivity && isMainActivity) { 9512675f769673f69b0661ddee346292f25cb30a296Maurice Chu String8 aName(getComponentName(pkg, activityName)); 9520a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLauncherActivity) { 9530a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("launchable-activity:"); 9549eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 9559eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 9569eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 9570a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s'\n", 9599eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 9609eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string()); 9610a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLeanbackLauncherActivity) { 9630a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("leanback-launchable-activity:"); 9649eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 9659eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 9669eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 9670a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9680a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s' banner='%s'\n", 9699eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 9709eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string(), 9719eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityBanner.string()).string()); 972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasIntentFilter) { 975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherActivities |= withinActivity; 976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherReceivers |= withinReceiver; 977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherServices |= withinService; 97894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 97994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (withinService) { 98094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && 98194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 98294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && 98394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 98494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 9899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 9910a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 4) { 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinIntentFilter) { 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinActivity) { 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMainActivity |= actMainActivity; 9969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasLauncher |= catLauncher; 9979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraActivity |= actCamera; 9989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraSecureActivity |= actCameraSecure; 9999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; 1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinReceiver) { 1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWidgetReceivers |= actWidgetReceivers; 1002a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasDeviceAdminReceiver |= (actDeviceAdminEnabled && 1003a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission); 1004a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); 1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinService) { 1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasImeService |= actImeService; 1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWallpaperService |= actWallpaperService; 1008a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasAccessibilityService |= (actAccessibilityService && 1009a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission); 1010a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasPrintService |= (actPrintService && hasBindPrintServicePermission); 10119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasNotificationListenerService |= actNotificationListenerService && 10129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission; 1013eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasDreamService |= actDreamService && hasBindDreamServicePermission; 1014a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherServices |= (!actImeService && !actWallpaperService && 101594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski !actAccessibilityService && !actPrintService && 10169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actHostApduService && !actOffHostApduService && 10179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actNotificationListenerService); 10189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 10199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; 1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinIntentFilter = false; 1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 10309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski 10319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 10329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 10339cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 10349cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 10359cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 10369cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d, %s\n", depth, tag.string()); 1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pkg = getAttribute(tree, NULL, "package", NULL); 10442675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: name='%s' ", 10452675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(pkg.string()).string()); 1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error); 1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string()); 1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (versionCode > 0) { 1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='%d' ", versionCode); 1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='' "); 1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error); 1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); 1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 10612675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("versionName='%s'\n", 10622675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(versionName.string()).string()); 1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2) { 1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "application") { 1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = true; 1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 label; 1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setLocale(localeStr != NULL ? localeStr : ""); 1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (llabel != "") { 1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 10772675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-label:'%s'\n", 10782675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (label == "") { 1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-label-%s:'%s'\n", localeStr, 10842675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config tmpConfig = config; 1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tmpConfig.density = densities[i]; 1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(tmpConfig); 1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (icon != "") { 10962675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-icon-%d:'%s'\n", densities[i], 10972675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(icon.string()).string()); 1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); 1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0); 1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string()); 1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 11122675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application: label='%s' ", 11132675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(label.string()).string()); 11142675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string()); 1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (testOnly != 0) { 1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("testOnly='%d'\n", testOnly); 1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0); 1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string()); 1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (debuggable != 0) { 1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-debuggable\n"); 1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-sdk") { 1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); 1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error); 1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", 1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut") targetSdk = 4; 11382675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("sdkVersion:'%s'\n", 11392675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("sdkVersion:'%d'\n", code); 1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1); 1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != -1) { 1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("maxSdkVersion:'%d'\n", code); 1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error); 1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", 1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut" && targetSdk < 4) targetSdk = 4; 11582675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("targetSdkVersion:'%s'\n", 11592675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < code) { 1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("targetSdkVersion:'%d'\n", code); 1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-configuration") { 1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqTouchScreen = getIntegerAttribute(tree, 1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR, NULL, 0); 1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqKeyboardType = getIntegerAttribute(tree, 1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR, NULL, 0); 1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqHardKeyboard = getIntegerAttribute(tree, 1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR, NULL, 0); 1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqNavigation = getIntegerAttribute(tree, 1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR, NULL, 0); 1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqFiveWayNav = getIntegerAttribute(tree, 1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR, NULL, 0); 1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-configuration:"); 1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqTouchScreen != 0) { 1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqTouchScreen='%d'", reqTouchScreen); 1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqKeyboardType != 0) { 1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqKeyboardType='%d'", reqKeyboardType); 1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqHardKeyboard != 0) { 1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqHardKeyboard='%d'", reqHardKeyboard); 1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqNavigation != 0) { 1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqNavigation='%d'", reqNavigation); 1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqFiveWayNav != 0) { 1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqFiveWayNav='%d'", reqFiveWayNav); 1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1194ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "supports-input") { 1195ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = true; 1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-screens") { 1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = getIntegerAttribute(tree, 1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR, NULL, 1); 1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = getIntegerAttribute(tree, 1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR, NULL, 1); 1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = getIntegerAttribute(tree, 1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR, NULL, 1); 1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = getIntegerAttribute(tree, 1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR, NULL, 1); 1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = getIntegerAttribute(tree, 1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR, NULL, 1); 1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski requiresSmallestWidthDp = getIntegerAttribute(tree, 1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0); 1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatibleWidthLimitDp = getIntegerAttribute(tree, 1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0); 1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largestWidthLimitDp = getIntegerAttribute(tree, 1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0); 1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-feature") { 1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int req = getIntegerAttribute(tree, 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR, NULL, 1); 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "android.hardware.camera") { 1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specCameraFeature = true; 1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.camera.autofocus") { 1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // these have no corresponding permission to check for, 1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but should imply the foundational camera permission 1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski reqCameraAutofocusFeature = reqCameraAutofocusFeature || req; 1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specCameraAutofocusFeature = true; 1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (req && (name == "android.hardware.camera.flash")) { 1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // these have no corresponding permission to check for, 1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but should imply the foundational camera permission 1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski reqCameraFlashFeature = true; 1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.location") { 1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specLocationFeature = true; 1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.location.network") { 1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specNetworkLocFeature = true; 1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski reqNetworkLocFeature = reqNetworkLocFeature || req; 1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.location.gps") { 1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specGpsFeature = true; 1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski reqGpsFeature = reqGpsFeature || req; 1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.bluetooth") { 1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specBluetoothFeature = true; 1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.touchscreen") { 1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specTouchscreenFeature = true; 1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specMultitouchFeature = true; 1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct") { 1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req; 1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.microphone") { 1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specMicrophoneFeature = true; 1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.wifi") { 1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specWiFiFeature = true; 1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.telephony") { 1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specTelephonyFeature = true; 1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (req && (name == "android.hardware.telephony.gsm" || 1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.hardware.telephony.cdma")) { 1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // these have no corresponding permission to check for, 1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but should imply the foundational telephony permission 1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski reqTelephonySubFeature = true; 1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.screen.portrait") { 1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specScreenPortraitFeature = true; 1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.hardware.screen.landscape") { 1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski specScreenLandscapeFeature = true; 1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature%s:'%s'\n", 12642675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", 12652675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int vers = getIntegerAttribute(tree, 1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR, &error); 1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error == "") { 1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-gl-es:'0x%x'\n", vers); 1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-permission") { 1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "android.permission.CAMERA") { 1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasCameraPermission = true; 1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_FINE_LOCATION") { 1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasGpsPermission = true; 1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { 1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMockLocPermission = true; 1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { 1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasCoarseLocPermission = true; 1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || 1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.INSTALL_LOCATION_PROVIDER") { 1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasGeneralLocPermission = true; 1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.BLUETOOTH" || 1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.BLUETOOTH_ADMIN") { 1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasBluetoothPermission = true; 1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.RECORD_AUDIO") { 1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasRecordAudioPermission = true; 1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_WIFI_STATE" || 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_STATE" || 1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { 1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWiFiPermission = true; 1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.CALL_PHONE" || 1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CALL_PRIVILEGED" || 1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.MODIFY_PHONE_STATE" || 1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.PROCESS_OUTGOING_CALLS" || 1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.READ_SMS" || 1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_SMS" || 1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_MMS" || 1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_WAP_PUSH" || 1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.SEND_SMS" || 1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_APN_SETTINGS" || 1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_SMS") { 1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasTelephonyPermission = true; 1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { 1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { 1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadExternalStoragePermission = true; 1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_PHONE_STATE") { 1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadPhoneStatePermission = true; 1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CONTACTS") { 1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadContactsPermission = true; 1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CONTACTS") { 1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteContactsPermission = true; 1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CALL_LOG") { 1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadCallLogPermission = true; 1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CALL_LOG") { 1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteCallLogPermission = true; 1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 132358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 132458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 132558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0, 132658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1)); 132758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } else { 1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-package") { 1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13352675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("uses-package:'%s'\n", 13362675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "original-package") { 1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13452675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("original-package:'%s'\n", 13462675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-gl-texture") { 1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13552675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("supports-gl-texture:'%s'\n", 13562675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "compatible-screens") { 13639cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski printCompatibleScreens(tree, &error); 13649cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (error != "") { 13659cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR getting compatible screens: %s\n", 13669cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski error.string()); 13679cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 13689cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "package-verifier") { 1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error); 1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (publicKey != "" && error == "") { 1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("package-verifier: name='%s' publicKey='%s'\n", 13762675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string(), 13772675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(publicKey.string()).string()); 1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1381ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (depth == 3) { 1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 13859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 138794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory = false; 138894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory = false; 138994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindDeviceAdminPermission = false; 139094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindInputMethodPermission = false; 139194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindAccessibilityServicePermission = false; 139294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindPrintServicePermission = false; 139394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = false; 13949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes = false; 13959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = false; 1396eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = false; 1397ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinApplication) { 1398ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if(tag == "activity") { 1399ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinActivity = true; 1400ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityName = getAttribute(tree, NAME_ATTR, &error); 1401ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1402ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1403ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1404ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1405ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1407ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 1408ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1409ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", 1410ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1411ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1412ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1414ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1415ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1416ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1417ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1418ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1419ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 14210a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error); 14220a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (error != "") { 14230a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", 14240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn error.string()); 14250a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn goto bail; 14260a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 14270a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn 1428ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright int32_t orien = getResolvedIntegerAttribute(&res, tree, 1429ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright SCREEN_ORIENTATION_ATTR, &error); 1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error == "") { 1431ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (orien == 0 || orien == 6 || orien == 8) { 1432ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests landscape, sensorLandscape, or reverseLandscape. 1433ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright reqScreenLandscapeFeature = true; 1434ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (orien == 1 || orien == 7 || orien == 9) { 1435ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests portrait, sensorPortrait, or reversePortrait. 1436ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright reqScreenPortraitFeature = true; 1437ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1439ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "uses-library") { 1440ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright String8 libraryName = getAttribute(tree, NAME_ATTR, &error); 1441ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1442ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1443ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for uses-library" 1444ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1445ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1446ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1447ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright int req = getIntegerAttribute(tree, 1448ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright REQUIRED_ATTR, NULL, 1); 1449ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("uses-library%s:'%s'\n", 14502675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", ResTable::normalizeForOutput( 14512675f769673f69b0661ddee346292f25cb30a296Maurice Chu libraryName.string()).string()); 1452ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "receiver") { 1453ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinReceiver = true; 1454ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright receiverName = getAttribute(tree, NAME_ATTR, &error); 1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1456ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1457ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1458ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for receiver:" 1459ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1460ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1461ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1462a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1463a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 permission = getAttribute(tree, PERMISSION_ATTR, &error); 1464a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1465a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_DEVICE_ADMIN") { 1466a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission = true; 1467a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1468a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1469a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1470a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " receiver '%s': %s\n", receiverName.string(), error.string()); 1471a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1472ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "service") { 1473ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinService = true; 1474ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright serviceName = getAttribute(tree, NAME_ATTR, &error); 1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1476ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1477ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1478ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "service:%s\n", error.string()); 1479ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1480ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1481a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1482a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 permission = getAttribute(tree, PERMISSION_ATTR, &error); 1483a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1484a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_INPUT_METHOD") { 1485a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindInputMethodPermission = true; 1486a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") { 1487a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission = true; 1488a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_PRINT_SERVICE") { 1489a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindPrintServicePermission = true; 149094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (permission == "android.permission.BIND_NFC_SERVICE") { 149194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = true; 14929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { 14939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = true; 1494eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (permission == "android.permission.BIND_DREAM_SERVICE") { 1495eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = true; 1496a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1497a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1498a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1499a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " service '%s': %s\n", serviceName.string(), error.string()); 1500a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 15019d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (tag == "provider") { 15029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = true; 15039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 15049d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error); 15059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:" 15079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 15119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree, 15129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR, &error); 15139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:" 15159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 15199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error); 15209d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:" 15229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 15269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes |= exported && grantUriPermissions && 15279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski permission == "android.permission.MANAGE_DOCUMENTS"; 15289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1529ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (bundle->getIncludeMetaData() && tag == "meta-data") { 1530b71adb6571aa740f4fa794602133f708e1b96545Adam Lesinski String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error); 1531ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1532ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1533ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "meta-data:%s\n", error.string()); 1534ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1535ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 15362675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("meta-data: name='%s' ", 15372675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(metaDataName.string()).string()); 153876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"), 153976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu &error); 1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 154176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu // Try looking for a RESOURCE_ATTR 154276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu error = ""; 154376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR, 154476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8("resource"), &error); 1545ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 154676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu fprintf(stderr, "ERROR getting 'android:value' or " 154776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "'android:resource' attribute for " 154876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "meta-data:%s\n", error.string()); 1549ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1550ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1551ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 155276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("\n"); 1553ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (withinSupportsInput && tag == "input-type") { 1554ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright String8 name = getAttribute(tree, NAME_ATTR, &error); 1555ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (name != "" && error == "") { 1556ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.add(name); 1557ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1558ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1559ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1563a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 156494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 4) { 156594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "intent-filter") { 156694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasIntentFilter = true; 156794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinIntentFilter = true; 156894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actMainActivity = false; 156994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWidgetReceivers = false; 157094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actImeService = false; 157194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWallpaperService = false; 157294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actAccessibilityService = false; 157394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actPrintService = false; 157494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actDeviceAdminEnabled = false; 157594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = false; 157694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = false; 15779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = false; 15789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = false; 1579eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = false; 15809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = false; 15819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = false; 15829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = false; 158394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (withinService && tag == "meta-data") { 158494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 158594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 158694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute for" 158794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 158894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 158994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 159094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 159194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service" || 159294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski name == "android.nfc.cardemulation.off_host_apdu_service") { 159394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool offHost = true; 159494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service") { 159594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost = false; 159694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 159794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 159894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error); 159994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 160094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:resource' attribute for" 160194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 160294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 160394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 160494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 160594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories = getNfcAidCategories(assets, xmlPath, 160694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost, &error); 160794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 160894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting AID category for service '%s'\n", 160994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski serviceName.string()); 161094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 161194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 161294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 161394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const size_t catLen = categories.size(); 161494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski for (size_t i = 0; i < catLen; i++) { 161594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool paymentCategory = (categories[i] == "payment"); 161694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (offHost) { 161794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory |= paymentCategory; 161894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 161994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory |= paymentCategory; 162094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 162194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 162294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 162394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1624a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if ((depth == 5) && withinIntentFilter) { 1625a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 action; 1626a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "action") { 1627a5018c900f126ee8424c82497f32983873db741bAdam Lesinski action = getAttribute(tree, NAME_ATTR, &error); 1628a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1629a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1630a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1631a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1632a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1633a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1634a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1635a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.MAIN") { 1636a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isMainActivity = true; 1637a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actMainActivity = true; 16389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA" || 16399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski action == "android.media.action.VIDEO_CAMERA") { 16409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = true; 16419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") { 16429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = true; 1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1644a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinReceiver) { 1645a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 1646a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWidgetReceivers = true; 1647a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") { 1648a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actDeviceAdminEnabled = true; 1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1650a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinService) { 1651a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.view.InputMethod") { 1652a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actImeService = true; 1653a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.service.wallpaper.WallpaperService") { 1654a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWallpaperService = true; 1655a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.accessibilityservice.AccessibilityService") { 1656a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actAccessibilityService = true; 1657a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.printservice.PrintService") { 1658a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actPrintService = true; 165994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { 166094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = true; 166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { 166294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = true; 16639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.service.notification.NotificationListenerService") { 16649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = true; 1665eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (action == "android.service.dreams.DreamService") { 1666eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = true; 16679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 16699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (action == "android.content.action.DOCUMENTS_PROVIDER") { 16709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = true; 1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1673a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.SEARCH") { 1674a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isSearchable = true; 1675a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1676a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1678a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "category") { 1679a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 category = getAttribute(tree, NAME_ATTR, &error); 1680a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1681a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'name' attribute: %s\n", 1682a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1683a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1684a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1685a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1686a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (category == "android.intent.category.LAUNCHER") { 1687a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isLauncherActivity = true; 16880a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } else if (category == "android.intent.category.LEANBACK_LAUNCHER") { 16890a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isLeanbackLauncherActivity = true; 16909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (category == "android.intent.category.HOME") { 16919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = true; 1692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-1.6 implicitly granted permission compatibility logic 1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 4) { 1700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteExternalStoragePermission) { 170158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE")); 170258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"), 170358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadPhoneStatePermission) { 170758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_PHONE_STATE")); 170858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"), 170958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the application has requested WRITE_EXTERNAL_STORAGE, we will 1714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // force them to always take READ_EXTERNAL_STORAGE as well. We always 1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // do this (regardless of target API version) because we can't have 1716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // an app with write permission but not read permission. 1717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { 171858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE")); 171958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 172058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("requested WRITE_EXTERNAL_STORAGE")); 1721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-JellyBean call log permission compatibility. 1724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 16) { 1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadCallLogPermission && hasReadContactsPermission) { 172658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_CALL_LOG")); 172758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"), 172858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested READ_CONTACTS")); 1729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteCallLogPermission && hasWriteContactsPermission) { 173158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_CALL_LOG")); 173258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"), 173358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested WRITE_CONTACTS")); 1734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* The following blocks handle printing "inferred" uses-features, based 1738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * on whether related features or permissions are used by the app. 1739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Note that the various spec*Feature variables denote whether the 1740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * relevant tag was *present* in the AndroidManfest, not that it was 1741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * present and set to true. 1742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 1743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Camera-related back-compatibility logic 1744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specCameraFeature) { 1745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqCameraFlashFeature) { 1746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app requested a sub-feature (autofocus or flash) and didn't 1747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the base camera feature, we infer that it meant to 1748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.camera'\n"); 1749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.camera'," \ 1750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.hardware.camera.flash feature'\n"); 1751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (reqCameraAutofocusFeature) { 1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app requested a sub-feature (autofocus or flash) and didn't 1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the base camera feature, we infer that it meant to 1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.camera'\n"); 1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.camera'," \ 1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.hardware.camera.autofocus feature'\n"); 1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (hasCameraPermission) { 17582675f769673f69b0661ddee346292f25cb30a296Maurice Chu // if app wants to use camera but didn't request the feature, we infer 1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // that it meant to, and further that it wants autofocus 1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (which was the 1.0 - 1.5 behavior) 1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.camera'\n"); 1762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specCameraAutofocusFeature) { 1763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.camera.autofocus'\n"); 1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.camera.autofocus'," \ 1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.permission.CAMERA permission'\n"); 1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Location-related back-compatibility logic 1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specLocationFeature && 1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission || 1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) { 1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app either takes a location-related permission or requests one of the 1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // sub-features, we infer that it also meant to request the base location feature 1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.location'\n"); 1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.location'," \ 1778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested a location access permission'\n"); 1779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specGpsFeature && hasGpsPermission) { 1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes GPS (FINE location) perm but does not request the GPS 1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // feature, we infer that it meant to 1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.location.gps'\n"); 1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.location.gps'," \ 1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.permission.ACCESS_FINE_LOCATION permission'\n"); 1786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specNetworkLocFeature && hasCoarseLocPermission) { 1788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes Network location (COARSE location) perm but does not request the 1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // network location feature, we infer that it meant to 1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.location.network'\n"); 1791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.location.network'," \ 1792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.permission.ACCESS_COARSE_LOCATION permission'\n"); 1793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Bluetooth-related compatibility logic 1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) { 1797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes a Bluetooth permission but does not request the Bluetooth 1798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // feature, we infer that it meant to 1799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.bluetooth'\n"); 1800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.bluetooth'," \ 1801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \ 1802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "permission and targetSdkVersion > 4'\n"); 1803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Microphone-related compatibility logic 1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specMicrophoneFeature && hasRecordAudioPermission) { 1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes the record-audio permission but does not request the microphone 1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // feature, we infer that it meant to 1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.microphone'\n"); 1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.microphone'," \ 1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.permission.RECORD_AUDIO permission'\n"); 1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // WiFi-related compatibility logic 1815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specWiFiFeature && hasWiFiPermission) { 1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes one of the WiFi permissions but does not request the WiFi 1817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // feature, we infer that it meant to 1818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.wifi'\n"); 1819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.wifi'," \ 1820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.permission.ACCESS_WIFI_STATE, " \ 1821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "android.permission.CHANGE_WIFI_STATE, or " \ 1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n"); 1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Telephony-related compatibility logic 1826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) { 1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes one of the telephony permissions or requests a sub-feature but 1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // does not request the base telephony feature, we infer that it meant to 1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.telephony'\n"); 1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.telephony'," \ 1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested a telephony-related permission or feature'\n"); 1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Touchscreen-related back-compatibility logic 1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specTouchscreenFeature) { // not a typo! 1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // all apps are presumed to require a touchscreen, unless they explicitly say 1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/> 1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Note that specTouchscreenFeature is true if the tag is present, regardless 1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // of whether its value is true or false, so this is safe 1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.touchscreen'\n"); 1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.touchscreen'," \ 1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'assumed you require a touch screen unless explicitly made optional'\n"); 1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specMultitouchFeature && reqDistinctMultitouchFeature) { 1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if app takes one of the telephony permissions or requests a sub-feature but 1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // does not request the base telephony feature, we infer that it meant to 1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.touchscreen.multitouch'\n"); 1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \ 1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'requested android.hardware.touchscreen.multitouch.distinct feature'\n"); 1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Landscape/portrait-related compatibility logic 1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!specScreenLandscapeFeature && !specScreenPortraitFeature) { 1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the app has specified any activities in its manifest 1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // that request a specific orientation, then assume that 1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // orientation is required. 1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqScreenLandscapeFeature) { 1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.screen.landscape'\n"); 1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.screen.landscape'," \ 1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'one or more activities have specified a landscape orientation'\n"); 1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqScreenPortraitFeature) { 1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-feature:'android.hardware.screen.portrait'\n"); 1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-implied-feature:'android.hardware.screen.portrait'," \ 1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "'one or more activities have specified a portrait orientation'\n"); 1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWidgetReceivers) { 18709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("app-widget"); 1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1872a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasDeviceAdminReceiver) { 18739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("device-admin"); 1874a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasImeService) { 18769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("ime"); 1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWallpaperService) { 18799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("wallpaper"); 1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1881a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasAccessibilityService) { 18829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("accessibility"); 1883a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1884a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasPrintService) { 18859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("print-service"); 1886a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 188794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (hasPaymentService) { 18889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("payment"); 18899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (isSearchable) { 18919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("search"); 18929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasDocumentsProvider) { 18949d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("document-provider"); 18959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasLauncher) { 18979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("launcher"); 18989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasNotificationListenerService) { 19009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("notification-listener"); 19019d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 1902eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock if (hasDreamService) { 1903eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock printComponentPresence("dream"); 1904eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } 19059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraActivity) { 19069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera"); 19079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraSecureActivity) { 19099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera-secure"); 19109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 19129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasMainActivity) { 19139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("main\n"); 191494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherActivities) { 1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-activities\n"); 1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 19189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasOtherReceivers) { 1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-receivers\n"); 1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherServices) { 1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-services\n"); 1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For modern apps, if screen size buckets haven't been specified 1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but the new width ranges have, then infer the buckets from them. 1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && requiresSmallestWidthDp > 0) { 1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatWidth = compatibleWidthLimitDp; 1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatWidth <= 0) { 1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatWidth = requiresSmallestWidthDp; 1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { 1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = -1; 1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = 0; 1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { 1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = 0; 1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { 1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = -1; 1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = 0; 1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { 1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = -1; 1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = 0; 1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Determine default values for any unspecified screen sizes, 1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // based on the target SDK of the package. As of 4 (donut) 1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the screen size support was introduced, so all default to 1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // enabled. 1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0) { 1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = targetSdk >= 4 ? -1 : 0; 1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen > 0) { 1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen > 0) { 1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = targetSdk >= 4 ? -1 : 0; 1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen > 0) { 1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Introduced in Gingerbread. 1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = targetSdk >= 9 ? -1 : 0; 1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (anyDensity > 0) { 1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || compatibleWidthLimitDp > 0) ? -1 : 0; 1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-screens:"); 1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen != 0) { 1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'small'"); 1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen != 0) { 1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'normal'"); 1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen != 0) { 1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'large'"); 1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen != 0) { 1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'xlarge'"); 1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); 1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp > 0) { 1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); 1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatibleWidthLimitDp > 0) { 1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); 1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largestWidthLimitDp > 0) { 1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("largest-width-limit:'%d'\n", largestWidthLimitDp); 1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("locales:"); 2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localeStr = "--_--"; 2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'", localeStr); 2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("densities:"); 2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%d'", densities[i]); 2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir != NULL) { 2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir->getFileCount() > 0) { 2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("native-code:"); 2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<dir->getFileCount(); i++) { 20242675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s'", ResTable::normalizeForOutput( 20252675f769673f69b0661ddee346292f25cb30a296Maurice Chu dir->getFileName(i).string()).string()); 2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete dir; 2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badger", option) == 0) { 2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s", CONSOLE_DATA); 2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("configurations", option) == 0) { 2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = configs.size(); 2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", configs[i].toString().string()); 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset) { 2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive. 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle) 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getUpdate()) { 2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* avoid confusion */ 2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: can't use '-u' with add\n"); 2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, true); 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'... (from gzip)\n", fileName); 2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getJunkPath()) { 2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 storageName = String8(fileName).getPathLeaf(); 20982675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s' as '%s'...\n", fileName, 20992675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(storageName.string()).string()); 2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, storageName.string(), 2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getCompressionMethod(), NULL); 2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'...\n", fileName); 2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": file not found\n"); 2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == ALREADY_EXISTS) { 2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": already exists in archive\n"); 2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "\n"); 2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive. 2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle) 2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, false); 2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName); 2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipEntry* entry; 2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByName(fileName); 2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry == NULL) { 2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s' NOT FOUND\n", fileName); 2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->remove(entry); 2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to delete '%s' from '%s'\n", 2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getFileSpecEntry(i), zipFileName); 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* update the archive */ 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->flush(); 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21823921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) { 2183fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numDirs = dir->getDirs().size(); 2184fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numDirs; i++) { 21853921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski bool ignore = ignoreConfig; 21863921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); 21873921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const char* dirStr = subDir->getLeaf().string(); 21883921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (!ignore && strstr(dirStr, "mipmap") == dirStr) { 21893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski ignore = true; 21903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 21913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = addResourcesToBuilder(subDir, builder, ignore); 2192fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2193fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2194fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2195fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2196fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2197fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numFiles = dir->getFiles().size(); 2198fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numFiles; i++) { 2199fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<AaptGroup> gp = dir->getFiles().valueAt(i); 2200fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numConfigs = gp->getFiles().size(); 2201fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t j = 0; j < numConfigs; j++) { 22023921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = NO_ERROR; 22033921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (ignoreConfig) { 22043921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22053921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } else { 22063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 2208fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2209fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Failed to add %s (%s) to builder.\n", 2210fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); 2211fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2212fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2213fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2214fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) { 2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (split->isBase()) { 2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return original; 2221fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2222fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2223fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 ext(original.getPathExtension()); 2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (ext == String8(".apk")) { 2225fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s%s", 2226fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski original.getBasePath().string(), 2227fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string(), 2228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ext.string()); 2229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s", original.string(), 2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string()); 2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files. 2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle) 2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* outputAPKFile; 2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retVal = 1; 2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptAssets> assets; 2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int N; 2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FILE* fp; 2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 dependencyFile; 2247fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<ApkBuilder> builder; 2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2249a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // -c en_XA or/and ar_XB means do pseudolocalization 2250fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<WeakResourceFilter> configFilter = new WeakResourceFilter(); 2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = configFilter->parse(bundle->getConfigurations()); 2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudo()) { 2256a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); 2257a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 2258fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudoBidi()) { 2259a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); 2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = bundle->getFileSpecCount(); 2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 226409384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { 2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no input files\n"); 2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile = bundle->getOutputAPKFile(); 2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure the filenames provided exist and are of the appropriate type. 2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FileType type; 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = getFileType(outputAPKFile); 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "ERROR: output file '%s' exists but is not regular file\n", 2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile); 2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Load the assets. 2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets = new AaptAssets(); 2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set up the resource gathering in assets if we're going to generate 2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dependency files. Every time we encounter a resource while slurping 2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the tree, we'll add it to these stores so we have full resource paths 2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to write to a dependency file. 2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> resPathStore = new FilePathStore; 2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullResPaths(resPathStore); 2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> assetPathStore = new FilePathStore; 2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullAssetPaths(assetPathStore); 2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = assets->slurpFromArgs(bundle); 2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->print(String8()); 2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2306fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Create the ApkBuilder, which will collect the compiled files 2307fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // to write to the final APK (or sets of APKs if we are building 2308fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // a Split APK. 2309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski builder = new ApkBuilder(configFilter); 2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If we are generating a Split APK, find out which configurations to split on. 2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (bundle->getSplitConfigurations().size() > 0) { 2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<String8>& splitStrs = bundle->getSplitConfigurations(); 2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splitStrs.size(); 2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::set<ConfigDescription> configs; 2317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) { 2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string()); 2319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = builder->createSplitForConfigs(configs); 2323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If they asked for any fileAs that need to be compiled, do so. 2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = buildResources(bundle, assets, builder); 2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != 0) { 2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At this point we've read everything and processed everything. From here 2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // on out it's just writing output files. 2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update symbols with information about which ones are needed as Java symbols. 2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->applyJavaSymbols(); 2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, do that here 2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is the packaging step, generate the dependency file next to 2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the output apk (e.g. bin/resources.ap_.d) 2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(outputAPKFile); 2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add the .d extension to the dependency file. 2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.append(".d"); 2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Else if this is the R.java dependency generation step, 2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // generate the dependency file in the R.java package subdirectory 2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java.d 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(bundle->getRClassDir()); 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.appendPath("R.java.d"); 2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure we have a clean dependency file to start with 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "w"); 2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out R.java constants 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets->havePrivateSymbols()) { 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getCustomPackage() == NULL) { 2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file into the appropriate class directory 2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java 2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), true); 2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 customPkg(bundle->getCustomPackage()); 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, customPkg, true); 2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we have library files, we're going to write our R.java file into 2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the appropriate class directory for those libraries as well. 2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/lib/R.java 2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getExtraPackages() != NULL) { 2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Split on colon 2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 libs(bundle->getExtraPackages()); 2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); 2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (packageString != NULL) { 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file out with the correct package name 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, String8(packageString), true); 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski packageString = strtok(NULL, ":"); 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski libs.unlockBuffer(); 2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), false); 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true); 2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out the ProGuard file 2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeProguardFile(bundle, assets); 2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the apk 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2418fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Gather all resources and add them to the APK Builder. The builder will then 2419fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // figure out which Split they belong in. 2420fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = addResourcesToBuilder(assets, builder); 2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2424fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2425fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<sp<ApkSplit> >& splits = builder->getSplits(); 2426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splits.size(); 2427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const sp<ApkSplit>& split = splits[i]; 2429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 outputPath = buildApkName(String8(outputAPKFile), split); 2430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = writeAPK(bundle, outputPath, split); 2431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string()); 2433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, we need to finish up here. 2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the writeResourceSymbols and writeAPK functions have already written the target 2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // half of the dependency file, now we need to write the prerequisites. (files that 2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the R.java file or .ap_ file depend on) 2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now that writeResourceSymbols or writeAPK has taken care of writing 2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the targets to our dependency file, we'll write the prereqs 2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "a+"); 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " : "); 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool includeRaw = (outputAPKFile != NULL); 2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Also manually add the AndroidManifeset since it's not under res/ or assets/ 2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and therefore was not added to our pathstores during slurping 2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); 2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retVal = 0; 2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos::printErrors(stderr); 2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return retVal; 2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching 2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS 2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -S flag points to a source directory containing drawable* folders 2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -C flag points to destination directory. The folder structure in the 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * source directory will be mirrored to the destination (cache) directory 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Destination directory will be updated to match the PNG files in 24722675f769673f69b0661ddee346292f25cb30a296Maurice Chu * the source directory. 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle) 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching PNG Files in "); 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); 2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski updatePreProcessedCache(bundle); 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag 2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -i points to a single png file 2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -o points to a single png output file 2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle) 2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); 2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); 2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 input(bundle->getSingleCrunchInputFile()); 2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 output(bundle->getSingleCrunchOutputFile()); 2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { 2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we can't return the status_t as it gets truncate to the lower 8 bits. 2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 42; 2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = { 2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, 2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, 2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, 2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, 2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, 2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, 2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, 2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, 2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, 2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, 2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, 2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, 2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, 2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, 2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, 2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, 2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 2671