1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include "AaptXml.h" 7fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h" 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h" 92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h" 102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h> 162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h> 172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h> 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h> 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h> 212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h> 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h> 242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h> 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 266f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <iostream> 276f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <string> 286f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <sstream> 296f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#ifndef AAPT_VERSION 33ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski #define AAPT_VERSION "" 34ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#endif 35ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info. All the cool kids do it. 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle) 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 0) { 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("(ignoring extra arguments)\n"); 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 44ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n"); 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only. The call fails if the file doesn't exist. 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName) 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip; 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, ZipFile::kOpenReadOnly); 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' not found\n", fileName); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == PERMISSION_DENIED) { 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileName); 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write. The file will be created if it doesn't 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set. 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate) 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int flags; 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags = ZipFile::kOpenReadWrite; 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (okayToCreate) { 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags |= ZipFile::kOpenCreate; 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, flags); 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = NULL; 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method. 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method) 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (method == ZipEntry::kCompressStored) { 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Stored"; 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (method == ZipEntry::kCompressDeflated) { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Deflated"; 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Unknown"; 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression). 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen) 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!uncompressedLen) { 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing. 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip" 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command. 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle) 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ZipEntry* entry; 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long totalUncLen, totalCompLen; 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 1) { 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: specify zip file name (only)\n"); 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadOnly(zipFileName); 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int count, i; 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Archive: %s\n", zipFileName); 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen = totalCompLen = 0; 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski count = zip->getNumEntries(); 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i = 0; i < count; i++) { 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByIndex(i); 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char dateBuf[32]; 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time_t when; 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski when = entry->getModWhen(); 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localtime(&when)); 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getUncompressedLen(), 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compressionName(entry->getCompressionMethod()), 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getCompressedLen(), 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(entry->getUncompressedLen(), 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCompressedLen()), 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (size_t) entry->getLFHOffset(), 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dateBuf, 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCRC32(), 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getFileName()); 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", entry->getFileName()); 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen += entry->getUncompressedLen(); 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen += entry->getCompressedLen(); 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------- --- -------\n"); 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %7ld %2d%% %d files\n", 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen, 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen, 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(totalUncLen, totalCompLen), 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->getNumEntries()); 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getAndroidList()) { 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(zipFileName), NULL)) { 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo resource table found.\n"); 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nResource table:\n"); 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(false); 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 249ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, 25076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu uint32_t attrRes, String8 attrLabel, String8* outError) 25176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 253ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError); 25476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 25576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 25676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 25776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 259ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError); 2602675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 2612675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 26276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 26676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 26776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 26876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 26976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 276a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 2779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 2789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 27994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 301caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski INSTALL_LOCATION_ATTR = 0x010102b7, 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 30894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 3090a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3122675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3212675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3232675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 3449cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 3459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 3469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 3479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 3489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 3499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 351ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenSize = AaptXml::getIntegerAttribute(tree, 352ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_SIZE_ATTR); 353ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenDensity = AaptXml::getIntegerAttribute(tree, 354ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_DENSITY_ATTR); 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 36758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) { 36858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 36958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 37058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 37158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 37258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 37358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 37858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 37958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 38058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 38158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 38258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 38358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) { 38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-implied-permission: name='%s' reason='%s'\n", 38658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string(), 38758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(reason.string()).string()); 38858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 38958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 39094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, 39194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 39294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 39394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 39494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 39594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 39694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 39794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 39894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 39994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 40094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 40294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 40394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 40594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 40694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 40794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 41094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 41194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 41294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 41394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 4149cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4169cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4179cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4189cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4199cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 42094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 42394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 42494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 42694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 4279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 43394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 43494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 43694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 440ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error); 44194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 44294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 44494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 45194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 45294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 45394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 45494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 4559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 4569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 4579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 4589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 4592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to 4612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason. 4622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature { 4642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Name of the implied feature. 4662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name; 4682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * List of human-readable reasons for why this feature was implied. 4712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski SortedVector<String8> reasons; 4732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 4742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml 4772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup { 479d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup() : openGLESVersion(-1) {} 480d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 4812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Human readable label 4832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 label; 4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Explicit features defined in the group 4882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, bool> features; 490d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 491d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski /** 492d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski * OpenGL ES version required 493d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski */ 494d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int openGLESVersion; 4952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 4962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures, 4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const char* name, const char* reason) { 4992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name8(name); 5002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ssize_t idx = impliedFeatures->indexOfKey(name8); 5012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (idx < 0) { 5022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski idx = impliedFeatures->add(name8, ImpliedFeature()); 5032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).name = name8; 5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).reasons.add(String8(reason)); 5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp, 5092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) { 5102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("feature-group: label='%s'\n", grp.label.string()); 5112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 512d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (grp.openGLESVersion > 0) { 513d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski printf(" uses-gl-es: '0x%x'\n", grp.openGLESVersion); 514d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 515d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 5162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatures = grp.features.size(); 5172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatures; i++) { 5182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features[i]) { 5192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 5202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const String8& featureName = grp.features.keyAt(i); 5232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", 5242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ResTable::normalizeForOutput(featureName.string()).string()); 5252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numImpliedFeatures = 5282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski (impliedFeatures != NULL) ? impliedFeatures->size() : 0; 5292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numImpliedFeatures; i++) { 5302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i); 5312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(impliedFeature.name) >= 0) { 5322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // The feature is explicitly set, no need to use implied 5332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // definition. 5342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 5352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 printableFeatureName(ResTable::normalizeForOutput( 5382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeature.name.string())); 5392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", printableFeatureName.string()); 5402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-implied-feature: name='%s' reason='", 5412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printableFeatureName.string()); 5422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numReasons = impliedFeature.reasons.size(); 5432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numReasons; j++) { 5442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("%s", impliedFeature.reasons[j].string()); 5452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (j + 2 < numReasons) { 5462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", "); 5472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (j + 1 < numReasons) { 5482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", and "); 5492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("'\n"); 5522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) { 5562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (name == "android.hardware.camera.autofocus" || 5572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.camera.flash") { 5582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.camera"), true); 5592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.location.gps" || 5602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.location.network") { 5612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.location"), true); 5622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 5632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 5642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct") { 5652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen.multitouch"), true); 5662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 567d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else if (name == "android.hardware.opengles.aep") { 568d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski const int openGLESVersion31 = 0x00030001; 569d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (openGLESVersion31 > grp->openGLESVersion) { 570d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp->openGLESVersion = openGLESVersion31; 571d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 5722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 597f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 60991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 620c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; 621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 62663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 62725e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (res.getError() != NO_ERROR) { 62825e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 62963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 63063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski } 63163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 6322cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // The dynamicRefTable can be null if there are no resources for this asset cookie. 6332cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // This fine. 63463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); 635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski Asset* asset = NULL; 63763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 65563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 65663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 68263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 68863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 70063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); 701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 7279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 7289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 7299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 7309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 7319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 7329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 739ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 7402675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "permission") { 742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 743ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 7482675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("permission: %s\n", 7492675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "uses-permission") { 751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 752ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 75758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 758ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 759ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 7850a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 788ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 7892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski bool withinFeatureGroup = false; 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 7929d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 7989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 7999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 802a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 803a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 805a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 80694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 8079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 8089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 8109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 8119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 812eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 8139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 816a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 819a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 820a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 82194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 82294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 8249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 825eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 8269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 8279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 8289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 82994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 83094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 833a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 834a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 835a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 836a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 837a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 83894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 8399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 8409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 841eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 857e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If an app declares itself as multiArch, we report the 858e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // native libraries differently. 859e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool hasMultiArch = false; 860e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 8662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 8900a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 893ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 8942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 8952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup commonFeatures; 8962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski Vector<FeatureGroup> featureGroups; 8972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, ImpliedFeature> impliedFeatures; 8982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 903ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 904ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 905ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 906ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 9072675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 9082675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 909ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 910ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 911ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 912ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 913ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 914ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 915ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.clear(); 916ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 918ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = false; 9192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = false; 920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 3) { 9210a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (withinActivity && isMainActivity) { 9222675f769673f69b0661ddee346292f25cb30a296Maurice Chu String8 aName(getComponentName(pkg, activityName)); 9230a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLauncherActivity) { 9240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("launchable-activity:"); 9259eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 9269eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 9279eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 9280a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9290a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s'\n", 9309eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 9319eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string()); 9320a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9330a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLeanbackLauncherActivity) { 9340a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("leanback-launchable-activity:"); 9359eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 9369eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 9379eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 9380a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 9390a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s' banner='%s'\n", 9409eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 9419eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string(), 9429eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityBanner.string()).string()); 943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasIntentFilter) { 946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherActivities |= withinActivity; 947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherReceivers |= withinReceiver; 948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherServices |= withinService; 94994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 95094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (withinService) { 95194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && 95294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 95394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && 95494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 95594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 9609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 9620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; 963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 4) { 964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinIntentFilter) { 965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinActivity) { 966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMainActivity |= actMainActivity; 9679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasLauncher |= catLauncher; 9689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraActivity |= actCamera; 9699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraSecureActivity |= actCameraSecure; 9709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; 971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinReceiver) { 972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWidgetReceivers |= actWidgetReceivers; 973a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasDeviceAdminReceiver |= (actDeviceAdminEnabled && 974a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission); 975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); 976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinService) { 977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasImeService |= actImeService; 978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWallpaperService |= actWallpaperService; 979a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasAccessibilityService |= (actAccessibilityService && 980a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission); 981a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasPrintService |= (actPrintService && hasBindPrintServicePermission); 9829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasNotificationListenerService |= actNotificationListenerService && 9839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission; 984eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasDreamService |= actDreamService && hasBindDreamServicePermission; 985a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherServices |= (!actImeService && !actWallpaperService && 98694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski !actAccessibilityService && !actPrintService && 9879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actHostApduService && !actOffHostApduService && 9889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actNotificationListenerService); 9899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 9909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; 991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinIntentFilter = false; 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 10019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski 10029cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 10039cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 10049cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 10059cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 10069cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 10079cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d, %s\n", depth, tag.string()); 1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1014ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 10152675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: name='%s' ", 10162675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(pkg.string()).string()); 1017ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR, 1018ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1020ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", 1021ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (versionCode > 0) { 1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='%d' ", versionCode); 1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='' "); 1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1029ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 versionName = AaptXml::getResolvedAttribute(res, tree, 1030ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski VERSION_NAME_ATTR, &error); 1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1032ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", 1033ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 103625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("versionName='%s'", 10372675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(versionName.string()).string()); 103825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski 1039ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 splitName = AaptXml::getAttribute(tree, NULL, "split"); 104025d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski if (!splitName.isEmpty()) { 104125d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf(" split='%s'", ResTable::normalizeForOutput( 104225d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski splitName.string()).string()); 104325d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski } 1044ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 10455283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski String8 platformVersionName = AaptXml::getAttribute(tree, NULL, 10465283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski "platformBuildVersionName"); 10475283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski printf(" platformBuildVersionName='%s'", platformVersionName.string()); 104825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("\n"); 1049caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1050ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree, 1051ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski INSTALL_LOCATION_ATTR, &error); 1052caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (error != "") { 1053caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n", 1054caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski error.string()); 1055caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1056caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1057caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1058caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (installLocation >= 0) { 1059caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("install-location:'"); 1060caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski switch (installLocation) { 1061caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 0: 1062caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("auto"); 1063caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1064caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 1: 1065caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("internalOnly"); 1066caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1067caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 2: 1068caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("preferExternal"); 1069caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1070caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski default: 1071caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "Invalid installLocation %d\n", installLocation); 1072caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1073caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1074caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("'\n"); 1075caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2) { 1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "application") { 1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = true; 1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 label; 1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setLocale(localeStr != NULL ? localeStr : ""); 1086ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, 1087ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (llabel != "") { 1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 10912675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-label:'%s'\n", 10922675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (label == "") { 1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-label-%s:'%s'\n", localeStr, 10982675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config tmpConfig = config; 1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tmpConfig.density = densities[i]; 1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(tmpConfig); 1108ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, 1109ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (icon != "") { 11112675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-icon-%d:'%s'\n", densities[i], 11122675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(icon.string()).string()); 1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1117ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error); 1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1119ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1120ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1123ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0, 1124ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1126ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", 1127ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 11302675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application: label='%s' ", 11312675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(label.string()).string()); 11322675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string()); 1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (testOnly != 0) { 1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("testOnly='%d'\n", testOnly); 1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1137ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree, 1138ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski DEBUGGABLE_ATTR, 0, &error); 1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1140ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", 1141ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (debuggable != 0) { 1145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-debuggable\n"); 1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1147e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1148e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // We must search by name because the multiArch flag hasn't been API 1149e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // frozen yet. 1150e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, 1151e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski "multiArch"); 1152e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (multiArchIndex >= 0) { 1153e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski Res_value value; 1154e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) { 1155e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (value.dataType >= Res_value::TYPE_FIRST_INT && 1156e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski value.dataType <= Res_value::TYPE_LAST_INT) { 1157e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski hasMultiArch = value.data; 1158e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1159e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1160e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-sdk") { 1162ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1165ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, 1166ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski MIN_SDK_VERSION_ATTR, &error); 1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", 1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut") targetSdk = 4; 11732675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("sdkVersion:'%s'\n", 11742675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("sdkVersion:'%d'\n", code); 1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1179ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR); 1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != -1) { 1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("maxSdkVersion:'%d'\n", code); 1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1183ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1186ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, 1187ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski TARGET_SDK_VERSION_ATTR, &error); 1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", 1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut" && targetSdk < 4) targetSdk = 4; 11942675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("targetSdkVersion:'%s'\n", 11952675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < code) { 1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("targetSdkVersion:'%d'\n", code); 1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-configuration") { 1203ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree, 1204ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_TOUCH_SCREEN_ATTR, 0); 1205ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree, 1206ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_KEYBOARD_TYPE_ATTR, 0); 1207ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree, 1208ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_HARD_KEYBOARD_ATTR, 0); 1209ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqNavigation = AaptXml::getIntegerAttribute(tree, 1210ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_NAVIGATION_ATTR, 0); 1211ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree, 1212ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_FIVE_WAY_NAV_ATTR, 0); 1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-configuration:"); 1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqTouchScreen != 0) { 1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqTouchScreen='%d'", reqTouchScreen); 1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqKeyboardType != 0) { 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqKeyboardType='%d'", reqKeyboardType); 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqHardKeyboard != 0) { 1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqHardKeyboard='%d'", reqHardKeyboard); 1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqNavigation != 0) { 1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqNavigation='%d'", reqNavigation); 1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqFiveWayNav != 0) { 1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqFiveWayNav='%d'", reqFiveWayNav); 1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1230ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "supports-input") { 1231ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = true; 1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-screens") { 1233ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski smallScreen = AaptXml::getIntegerAttribute(tree, 1234ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SMALL_SCREEN_ATTR, 1); 1235ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski normalScreen = AaptXml::getIntegerAttribute(tree, 1236ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski NORMAL_SCREEN_ATTR, 1); 1237ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski largeScreen = AaptXml::getIntegerAttribute(tree, 1238ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski LARGE_SCREEN_ATTR, 1); 1239ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski xlargeScreen = AaptXml::getIntegerAttribute(tree, 1240ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski XLARGE_SCREEN_ATTR, 1); 1241ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski anyDensity = AaptXml::getIntegerAttribute(tree, 1242ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ANY_DENSITY_ATTR, 1); 1243ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree, 1244ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0); 1245ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree, 1246ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0); 1247ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski largestWidthLimitDp = AaptXml::getIntegerAttribute(tree, 1248ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR, 0); 12492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (tag == "feature-group") { 12502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = true; 12512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup group; 1252ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error); 12532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (error != "") { 12542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski fprintf(stderr, "ERROR getting 'android:label' attribute:" 12552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski " %s\n", error.string()); 12562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski goto bail; 12572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 12582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski featureGroups.add(group); 12592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-feature") { 1261ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1263ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int req = AaptXml::getIntegerAttribute(tree, 1264ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRED_ATTR, 1); 1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 12662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski commonFeatures.features.add(name, req); 12672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (req) { 12682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addParentFeatures(&commonFeatures, name); 1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1271ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int vers = AaptXml::getIntegerAttribute(tree, 1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR, &error); 1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error == "") { 1274d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > commonFeatures.openGLESVersion) { 1275d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.openGLESVersion = vers; 1276d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-permission") { 1280ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "android.permission.CAMERA") { 1283d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.camera", 12842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_FINE_LOCATION") { 12872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.gps", 12882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 12902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 12912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { 12942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 12952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 12962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { 12982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.network", 12992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 13012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || 1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.INSTALL_LOCATION_PROVIDER") { 13062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 13072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.BLUETOOTH" || 1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.BLUETOOTH_ADMIN") { 13112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (targetSdk > 4) { 13122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 13132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 13152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 13162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "targetSdkVersion > 4"); 13172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.RECORD_AUDIO") { 13192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.microphone", 13202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_WIFI_STATE" || 1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_STATE" || 1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { 13252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.wifi", 13262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 13272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.CALL_PHONE" || 1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CALL_PRIVILEGED" || 1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.MODIFY_PHONE_STATE" || 1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.PROCESS_OUTGOING_CALLS" || 1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.READ_SMS" || 1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_SMS" || 1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_MMS" || 1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_WAP_PUSH" || 1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.SEND_SMS" || 1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_APN_SETTINGS" || 1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_SMS") { 13392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.telephony", 13402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8("requested a telephony permission").string()); 1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { 1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { 1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadExternalStoragePermission = true; 1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_PHONE_STATE") { 1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadPhoneStatePermission = true; 1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CONTACTS") { 1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadContactsPermission = true; 1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CONTACTS") { 1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteContactsPermission = true; 1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CALL_LOG") { 1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadCallLogPermission = true; 1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CALL_LOG") { 1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteCallLogPermission = true; 1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 135658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 135758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 1358ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 1359ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 136058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } else { 1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-package") { 1366ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13682675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("uses-package:'%s'\n", 13692675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "original-package") { 1376ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13782675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("original-package:'%s'\n", 13792675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-gl-texture") { 1386ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 13882675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("supports-gl-texture:'%s'\n", 13892675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "compatible-screens") { 13969cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski printCompatibleScreens(tree, &error); 13979cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (error != "") { 13989cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR getting compatible screens: %s\n", 13999cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski error.string()); 14009cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 14019cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "package-verifier") { 1404ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1406ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error); 1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (publicKey != "" && error == "") { 1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("package-verifier: name='%s' publicKey='%s'\n", 14092675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string(), 14102675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(publicKey.string()).string()); 1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1414ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (depth == 3) { 1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 14189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 142094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory = false; 142194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory = false; 142294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindDeviceAdminPermission = false; 142394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindInputMethodPermission = false; 142494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindAccessibilityServicePermission = false; 142594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindPrintServicePermission = false; 142694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = false; 14279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes = false; 14289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = false; 1429eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = false; 1430ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinApplication) { 1431ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if(tag == "activity") { 1432ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinActivity = true; 1433ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1434ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1435ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1436ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1437ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1438ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1440ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, 1441ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1442ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1443ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", 1444ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1445ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1446ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1448ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, 1449ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1450ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1451ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1452ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1453ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1454ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1456ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, 1457ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 14580a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (error != "") { 14590a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", 14600a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn error.string()); 14610a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn goto bail; 14620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 14630a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn 1464ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree, 1465ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright SCREEN_ORIENTATION_ATTR, &error); 1466ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error == "") { 1467ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (orien == 0 || orien == 6 || orien == 8) { 1468ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests landscape, sensorLandscape, or reverseLandscape. 14692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape", 14702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a landscape orientation"); 1471ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (orien == 1 || orien == 7 || orien == 9) { 1472ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests portrait, sensorPortrait, or reversePortrait. 14732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait", 14742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a portrait orientation"); 1475ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1477ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "uses-library") { 1478ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1479ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1480ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1481ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for uses-library" 1482ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1483ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1484ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1485ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int req = AaptXml::getIntegerAttribute(tree, 1486ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRED_ATTR, 1); 1487ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("uses-library%s:'%s'\n", 14882675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", ResTable::normalizeForOutput( 14892675f769673f69b0661ddee346292f25cb30a296Maurice Chu libraryName.string()).string()); 1490ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "receiver") { 1491ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinReceiver = true; 1492ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1494ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1495ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1496ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for receiver:" 1497ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1498ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1499ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1500a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1501ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR, 1502ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1503a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1504a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_DEVICE_ADMIN") { 1505a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission = true; 1506a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1507a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1508a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1509a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " receiver '%s': %s\n", receiverName.string(), error.string()); 1510a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1511ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "service") { 1512ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinService = true; 1513ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1515ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1516ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1517ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "service:%s\n", error.string()); 1518ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1519ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1520a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1521ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR, 1522ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1523a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1524a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_INPUT_METHOD") { 1525a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindInputMethodPermission = true; 1526a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") { 1527a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission = true; 1528a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_PRINT_SERVICE") { 1529a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindPrintServicePermission = true; 153094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (permission == "android.permission.BIND_NFC_SERVICE") { 153194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = true; 15329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { 15339d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = true; 1534eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (permission == "android.permission.BIND_DREAM_SERVICE") { 1535eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = true; 1536a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1537a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1538a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1539a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " service '%s': %s\n", serviceName.string(), error.string()); 1540a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 15419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (tag == "provider") { 15429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = true; 15439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1544ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski bool exported = AaptXml::getResolvedIntegerAttribute(res, tree, 1545ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski EXPORTED_ATTR, &error); 15469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:" 15489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1552ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute( 1553ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski res, tree, GRANT_URI_PERMISSIONS_ATTR, &error); 15549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:" 15569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1560ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getResolvedAttribute(res, tree, 1561ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski PERMISSION_ATTR, &error); 15629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 15639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:" 15649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 15659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 15669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 15679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 15689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes |= exported && grantUriPermissions && 15699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski permission == "android.permission.MANAGE_DOCUMENTS"; 15709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1571ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (bundle->getIncludeMetaData() && tag == "meta-data") { 1572ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 metaDataName = AaptXml::getResolvedAttribute(res, tree, 1573ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski NAME_ATTR, &error); 1574ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1575ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1576ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "meta-data:%s\n", error.string()); 1577ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1578ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 15792675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("meta-data: name='%s' ", 15802675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(metaDataName.string()).string()); 1581ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"), 158276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu &error); 1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 158476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu // Try looking for a RESOURCE_ATTR 158576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu error = ""; 1586ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printResolvedResourceAttribute(res, tree, RESOURCE_ATTR, 158776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8("resource"), &error); 1588ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 158976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu fprintf(stderr, "ERROR getting 'android:value' or " 159076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "'android:resource' attribute for " 159176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "meta-data:%s\n", error.string()); 1592ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1593ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1594ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 159576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("\n"); 1596ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (withinSupportsInput && tag == "input-type") { 1597ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1598ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (name != "" && error == "") { 1599ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.add(name); 1600ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1601ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1602ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 16062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (withinFeatureGroup && tag == "uses-feature") { 1607d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup& top = featureGroups.editTop(); 1608d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 1609ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error); 1610d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (name != "" && error == "") { 1611d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski top.features.add(name, true); 1612d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski addParentFeatures(&top, name); 1613d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else { 1614ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR, 1615ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1616d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (error == "") { 1617d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > top.openGLESVersion) { 1618d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski top.openGLESVersion = vers; 1619d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1620d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 16212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1622a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 162394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 4) { 162494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "intent-filter") { 162594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasIntentFilter = true; 162694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinIntentFilter = true; 162794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actMainActivity = false; 162894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWidgetReceivers = false; 162994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actImeService = false; 163094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWallpaperService = false; 163194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actAccessibilityService = false; 163294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actPrintService = false; 163394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actDeviceAdminEnabled = false; 163494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = false; 163594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = false; 16369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = false; 16379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = false; 1638eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = false; 16399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = false; 16409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = false; 16419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = false; 164294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (withinService && tag == "meta-data") { 1643ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 164494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 164594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute for" 164694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 164794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 164894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 164994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 165094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service" || 165194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski name == "android.nfc.cardemulation.off_host_apdu_service") { 165294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool offHost = true; 165394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service") { 165494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost = false; 165594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 165694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 1657ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 xmlPath = AaptXml::getResolvedAttribute(res, tree, 1658ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski RESOURCE_ATTR, &error); 165994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 166094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:resource' attribute for" 166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 166294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 166394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 166494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 166594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories = getNfcAidCategories(assets, xmlPath, 166694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost, &error); 166794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 166894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting AID category for service '%s'\n", 166994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski serviceName.string()); 167094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 167194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 167294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 167394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const size_t catLen = categories.size(); 167494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski for (size_t i = 0; i < catLen; i++) { 167594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool paymentCategory = (categories[i] == "payment"); 167694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (offHost) { 167794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory |= paymentCategory; 167894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 167994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory |= paymentCategory; 168094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 168194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 168294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 168394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1684a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if ((depth == 5) && withinIntentFilter) { 1685a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 action; 1686a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "action") { 1687ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski action = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1688a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1689a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1690a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1691a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1692a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1693a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1694a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1695a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.MAIN") { 1696a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isMainActivity = true; 1697a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actMainActivity = true; 16989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA" || 16999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski action == "android.media.action.VIDEO_CAMERA") { 17009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = true; 17019d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") { 17029d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = true; 1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1704a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinReceiver) { 1705a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 1706a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWidgetReceivers = true; 1707a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") { 1708a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actDeviceAdminEnabled = true; 1709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1710a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinService) { 1711a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.view.InputMethod") { 1712a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actImeService = true; 1713a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.service.wallpaper.WallpaperService") { 1714a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWallpaperService = true; 1715a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.accessibilityservice.AccessibilityService") { 1716a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actAccessibilityService = true; 1717a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.printservice.PrintService") { 1718a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actPrintService = true; 171994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { 172094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = true; 172194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { 172294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = true; 17239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.service.notification.NotificationListenerService") { 17249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = true; 1725eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (action == "android.service.dreams.DreamService") { 1726eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = true; 17279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 17289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 17299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (action == "android.content.action.DOCUMENTS_PROVIDER") { 17309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = true; 1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1733a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.SEARCH") { 1734a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isSearchable = true; 1735a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1736a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1738a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "category") { 1739ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1740a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1741a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'name' attribute: %s\n", 1742a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1743a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1744a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1745a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1746a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (category == "android.intent.category.LAUNCHER") { 1747a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isLauncherActivity = true; 17480a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } else if (category == "android.intent.category.LEANBACK_LAUNCHER") { 17490a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isLeanbackLauncherActivity = true; 17509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (category == "android.intent.category.HOME") { 17519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = true; 1752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-1.6 implicitly granted permission compatibility logic 1759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 4) { 1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteExternalStoragePermission) { 176158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE")); 176258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"), 176358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadPhoneStatePermission) { 176758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_PHONE_STATE")); 176858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"), 176958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the application has requested WRITE_EXTERNAL_STORAGE, we will 1774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // force them to always take READ_EXTERNAL_STORAGE as well. We always 1775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // do this (regardless of target API version) because we can't have 1776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // an app with write permission but not read permission. 1777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { 177858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE")); 177958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 178058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("requested WRITE_EXTERNAL_STORAGE")); 1781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-JellyBean call log permission compatibility. 1784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 16) { 1785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadCallLogPermission && hasReadContactsPermission) { 178658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_CALL_LOG")); 178758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"), 178858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested READ_CONTACTS")); 1789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteCallLogPermission && hasWriteContactsPermission) { 179158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_CALL_LOG")); 179258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"), 179358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested WRITE_CONTACTS")); 1794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen", 17982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "default feature for all apps"); 17992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 18002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatureGroups = featureGroups.size(); 18012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (numFeatureGroups == 0) { 18022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // If no <feature-group> tags were defined, apply auto-implied features. 18032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(commonFeatures, &impliedFeatures); 18042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 18052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else { 18062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // <feature-group> tags are defined, so we ignore implied features and 18072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatureGroups; i++) { 18082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup& grp = featureGroups.editItemAt(i); 18092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1810d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (commonFeatures.openGLESVersion > grp.openGLESVersion) { 1811d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.openGLESVersion = commonFeatures.openGLESVersion; 1812d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1813d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 18142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // Merge the features defined in the top level (not inside a <feature-group>) 18152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // with this feature group. 18162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numCommonFeatures = commonFeatures.features.size(); 18172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numCommonFeatures; j++) { 18182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) { 1819d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.features.add(commonFeatures.features.keyAt(j), 1820d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.features[j]); 18212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features.isEmpty()) { 18252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(grp); 18262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWidgetReceivers) { 18329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("app-widget"); 1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1834a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasDeviceAdminReceiver) { 18359d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("device-admin"); 1836a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasImeService) { 18389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("ime"); 1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWallpaperService) { 18419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("wallpaper"); 1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1843a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasAccessibilityService) { 18449d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("accessibility"); 1845a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1846a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasPrintService) { 18479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("print-service"); 1848a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 184994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (hasPaymentService) { 18509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("payment"); 18519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (isSearchable) { 18539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("search"); 18549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasDocumentsProvider) { 18569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("document-provider"); 18579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasLauncher) { 18599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("launcher"); 18609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasNotificationListenerService) { 18629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("notification-listener"); 18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 1864eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock if (hasDreamService) { 1865eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock printComponentPresence("dream"); 1866eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } 18679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraActivity) { 18689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera"); 18699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraSecureActivity) { 18719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera-secure"); 18729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 18749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasMainActivity) { 18759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("main\n"); 187694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherActivities) { 1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-activities\n"); 1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 18809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasOtherReceivers) { 1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-receivers\n"); 1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherServices) { 1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-services\n"); 1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For modern apps, if screen size buckets haven't been specified 1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but the new width ranges have, then infer the buckets from them. 1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && requiresSmallestWidthDp > 0) { 1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatWidth = compatibleWidthLimitDp; 1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatWidth <= 0) { 1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatWidth = requiresSmallestWidthDp; 1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { 1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = -1; 1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = 0; 1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { 1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = 0; 1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { 1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = -1; 1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = 0; 1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { 1911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = -1; 1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = 0; 1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Determine default values for any unspecified screen sizes, 1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // based on the target SDK of the package. As of 4 (donut) 1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the screen size support was introduced, so all default to 1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // enabled. 1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0) { 1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = targetSdk >= 4 ? -1 : 0; 1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen > 0) { 1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen > 0) { 1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = targetSdk >= 4 ? -1 : 0; 1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen > 0) { 1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Introduced in Gingerbread. 1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = targetSdk >= 9 ? -1 : 0; 1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (anyDensity > 0) { 1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || compatibleWidthLimitDp > 0) ? -1 : 0; 1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-screens:"); 1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen != 0) { 1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'small'"); 1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen != 0) { 1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'normal'"); 1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen != 0) { 1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'large'"); 1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen != 0) { 1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'xlarge'"); 1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); 1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp > 0) { 1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); 1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatibleWidthLimitDp > 0) { 1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); 1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largestWidthLimitDp > 0) { 1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("largest-width-limit:'%d'\n", largestWidthLimitDp); 1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("locales:"); 1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localeStr = "--_--"; 1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'", localeStr); 1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("densities:"); 1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%d'", densities[i]); 1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir != NULL) { 1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir->getFileCount() > 0) { 1984e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski SortedVector<String8> architectures; 1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<dir->getFileCount(); i++) { 1986e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.add(ResTable::normalizeForOutput( 1987e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski dir->getFileName(i).string())); 1988e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1989e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1990e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool outputAltNativeCode = false; 1991e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // A multiArch package is one that contains 64-bit and 1992e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit versions of native code and expects 3rd-party 1993e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // apps to load these native code libraries. Since most 1994e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 64-bit systems also support 32-bit apps, the apps 1995e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // loading this multiArch package's code may be either 1996e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit or 64-bit. 1997e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (hasMultiArch) { 1998e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If this is a multiArch package, report the 64-bit 1999e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // version only. Then as a separate entry, report the 2000e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // rest. 2001e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 2002e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If we report the 32-bit architecture, this APK will 2003e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // be installed on a 32-bit device, causing a large waste 2004e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // of bandwidth and disk space. This assumes that 2005e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // the developer of the multiArch package has also 2006e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // made a version that is 32-bit only. 2007e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 intel64("x86_64"); 2008e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 arm64("arm64-v8a"); 2009e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski ssize_t index = architectures.indexOf(intel64); 2010e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index < 0) { 2011e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski index = architectures.indexOf(arm64); 2012e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2013e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2014e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index >= 0) { 2015e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code: '%s'\n", architectures[index].string()); 2016e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.removeAt(index); 2017e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski outputAltNativeCode = true; 2018e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2019e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2020e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2021e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski const size_t archCount = architectures.size(); 2022e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (archCount > 0) { 2023e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (outputAltNativeCode) { 2024e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("alt-"); 2025e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2026e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code:"); 2027e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski for (size_t i = 0; i < archCount; i++) { 2028e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf(" '%s'", architectures[i].string()); 2029e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2030e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("\n"); 2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete dir; 2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badger", option) == 0) { 2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s", CONSOLE_DATA); 2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("configurations", option) == 0) { 2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = configs.size(); 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", configs[i].toString().string()); 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset) { 2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive. 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle) 2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getUpdate()) { 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* avoid confusion */ 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: can't use '-u' with add\n"); 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, true); 2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'... (from gzip)\n", fileName); 2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getJunkPath()) { 2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 storageName = String8(fileName).getPathLeaf(); 21022675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s' as '%s'...\n", fileName, 21032675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(storageName.string()).string()); 2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, storageName.string(), 2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getCompressionMethod(), NULL); 2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'...\n", fileName); 2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 2113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 2114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": file not found\n"); 2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == ALREADY_EXISTS) { 2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": already exists in archive\n"); 2117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "\n"); 2119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive. 2134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle) 2136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, false); 2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName); 2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipEntry* entry; 2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByName(fileName); 2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry == NULL) { 2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s' NOT FOUND\n", fileName); 2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->remove(entry); 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to delete '%s' from '%s'\n", 2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getFileSpecEntry(i), zipFileName); 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* update the archive */ 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->flush(); 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21863921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) { 2187fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numDirs = dir->getDirs().size(); 2188fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numDirs; i++) { 21893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski bool ignore = ignoreConfig; 21903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); 21913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const char* dirStr = subDir->getLeaf().string(); 21923921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (!ignore && strstr(dirStr, "mipmap") == dirStr) { 21933921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski ignore = true; 21943921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 21953921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = addResourcesToBuilder(subDir, builder, ignore); 2196fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2197fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2198fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2199fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2200fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2201fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numFiles = dir->getFiles().size(); 2202fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numFiles; i++) { 2203fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<AaptGroup> gp = dir->getFiles().valueAt(i); 2204fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numConfigs = gp->getFiles().size(); 2205fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t j = 0; j < numConfigs; j++) { 22063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = NO_ERROR; 22073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (ignoreConfig) { 22083921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22093921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } else { 22103921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 22113921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 2212fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2213fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Failed to add %s (%s) to builder.\n", 2214fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); 2215fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2216fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2217fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2218fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2219fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 2220fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2221fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2222fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) { 2223fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (split->isBase()) { 2224fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return original; 2225fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2226fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2227fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 ext(original.getPathExtension()); 2228fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (ext == String8(".apk")) { 2229fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s%s", 2230fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski original.getBasePath().string(), 2231fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string(), 2232fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ext.string()); 2233fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2234fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2235fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s", original.string(), 2236fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string()); 2237fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files. 2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle) 2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* outputAPKFile; 2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retVal = 1; 2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptAssets> assets; 2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int N; 2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FILE* fp; 2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 dependencyFile; 2251fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<ApkBuilder> builder; 2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2253a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // -c en_XA or/and ar_XB means do pseudolocalization 2254fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<WeakResourceFilter> configFilter = new WeakResourceFilter(); 2255fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = configFilter->parse(bundle->getConfigurations()); 2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2259fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudo()) { 2260a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); 2261a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 2262fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudoBidi()) { 2263a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); 2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = bundle->getFileSpecCount(); 2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 226809384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { 2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no input files\n"); 2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile = bundle->getOutputAPKFile(); 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure the filenames provided exist and are of the appropriate type. 2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FileType type; 2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = getFileType(outputAPKFile); 2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "ERROR: output file '%s' exists but is not regular file\n", 2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile); 2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Load the assets. 2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets = new AaptAssets(); 2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set up the resource gathering in assets if we're going to generate 2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dependency files. Every time we encounter a resource while slurping 2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the tree, we'll add it to these stores so we have full resource paths 2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to write to a dependency file. 2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> resPathStore = new FilePathStore; 2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullResPaths(resPathStore); 2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> assetPathStore = new FilePathStore; 2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullAssetPaths(assetPathStore); 2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = assets->slurpFromArgs(bundle); 2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->print(String8()); 2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Create the ApkBuilder, which will collect the compiled files 2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // to write to the final APK (or sets of APKs if we are building 2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // a Split APK. 2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski builder = new ApkBuilder(configFilter); 2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If we are generating a Split APK, find out which configurations to split on. 2316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (bundle->getSplitConfigurations().size() > 0) { 2317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<String8>& splitStrs = bundle->getSplitConfigurations(); 2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splitStrs.size(); 2319fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2320fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::set<ConfigDescription> configs; 2321fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) { 2322fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string()); 2323fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2324fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = builder->createSplitForConfigs(configs); 2327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2329fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2332fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If they asked for any fileAs that need to be compiled, do so. 2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 2335fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = buildResources(bundle, assets, builder); 2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != 0) { 2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At this point we've read everything and processed everything. From here 2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // on out it's just writing output files. 2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update symbols with information about which ones are needed as Java symbols. 2348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->applyJavaSymbols(); 2349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, do that here 2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is the packaging step, generate the dependency file next to 2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the output apk (e.g. bin/resources.ap_.d) 2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(outputAPKFile); 2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add the .d extension to the dependency file. 2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.append(".d"); 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Else if this is the R.java dependency generation step, 2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // generate the dependency file in the R.java package subdirectory 2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java.d 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(bundle->getRClassDir()); 2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.appendPath("R.java.d"); 2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure we have a clean dependency file to start with 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "w"); 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out R.java constants 2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets->havePrivateSymbols()) { 2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getCustomPackage() == NULL) { 2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file into the appropriate class directory 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java 23781e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), true, 23791e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski bundle->getBuildSharedLibrary()); 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 customPkg(bundle->getCustomPackage()); 23821e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, customPkg, true, 23831e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski bundle->getBuildSharedLibrary()); 2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we have library files, we're going to write our R.java file into 2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the appropriate class directory for those libraries as well. 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/lib/R.java 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getExtraPackages() != NULL) { 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Split on colon 2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 libs(bundle->getExtraPackages()); 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (packageString != NULL) { 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file out with the correct package name 23970f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba err = writeResourceSymbols(bundle, assets, String8(packageString), true, 23980f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba bundle->getBuildSharedLibrary()); 2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski packageString = strtok(NULL, ":"); 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski libs.unlockBuffer(); 2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 24071e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false); 2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 24111e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false); 2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out the ProGuard file 2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeProguardFile(bundle, assets); 2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the apk 2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2425fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Gather all resources and add them to the APK Builder. The builder will then 2426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // figure out which Split they belong in. 2427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = addResourcesToBuilder(assets, builder); 2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<sp<ApkSplit> >& splits = builder->getSplits(); 2433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splits.size(); 2434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const sp<ApkSplit>& split = splits[i]; 2436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 outputPath = buildApkName(String8(outputAPKFile), split); 2437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = writeAPK(bundle, outputPath, split); 2438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string()); 2440fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2441fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2442fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, we need to finish up here. 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the writeResourceSymbols and writeAPK functions have already written the target 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // half of the dependency file, now we need to write the prerequisites. (files that 2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the R.java file or .ap_ file depend on) 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now that writeResourceSymbols or writeAPK has taken care of writing 2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the targets to our dependency file, we'll write the prereqs 2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "a+"); 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " : "); 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool includeRaw = (outputAPKFile != NULL); 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); 2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Also manually add the AndroidManifeset since it's not under res/ or assets/ 2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and therefore was not added to our pathstores during slurping 2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); 2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retVal = 0; 2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos::printErrors(stderr); 2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return retVal; 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching 2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -S flag points to a source directory containing drawable* folders 2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -C flag points to destination directory. The folder structure in the 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * source directory will be mirrored to the destination (cache) directory 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Destination directory will be updated to match the PNG files in 24792675f769673f69b0661ddee346292f25cb30a296Maurice Chu * the source directory. 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle) 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching PNG Files in "); 2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); 2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); 2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski updatePreProcessedCache(bundle); 2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag 2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -i points to a single png file 2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -o points to a single png output file 2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle) 2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); 2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); 2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 input(bundle->getSingleCrunchInputFile()); 2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 output(bundle->getSingleCrunchOutputFile()); 2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { 2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we can't return the status_t as it gets truncate to the lower 8 bits. 2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 42; 2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 25136f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochezint runInDaemonMode(Bundle* bundle) { 25146f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Ready" << std::endl; 25156f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez for (std::string line; std::getline(std::cin, line);) { 25166f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez if (line == "quit") { 25176f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez return NO_ERROR; 25186f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 25196f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::stringstream ss; 25206f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez ss << line; 25216f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::string s; 25226f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez 25236f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::string command, parameterOne, parameterTwo; 25246f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::getline(ss, command, ' '); 25256f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::getline(ss, parameterOne, ' '); 25266f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::getline(ss, parameterTwo, ' '); 25276f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez if (command[0] == 's') { 25286f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez bundle->setSingleCrunchInputFile(parameterOne.c_str()); 25296f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez bundle->setSingleCrunchOutputFile(parameterTwo.c_str()); 25306f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Crunching " << parameterOne << std::endl; 25316f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez if (doSingleCrunch(bundle) != NO_ERROR) { 25326f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Error" << std::endl; 25336f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 25346f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Done" << std::endl; 25356f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } else { 25366f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez // in case of invalid command, just bail out. 25376f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cerr << "Unknown command" << std::endl; 25386f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez return -1; 25396f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 25406f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 25416f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez return -1; 25426f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez} 25436f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez 2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = { 2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 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, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, 2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, 2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, 2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, 2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, 2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, 2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, 2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, 2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, 2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, 2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, 2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, 2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, 2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, 2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, 2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 2709