Command.cpp revision caf797c84a6a2829662872e0df93fcd61da78d51
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h" 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h" 82c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h" 92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h" 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h> 152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h> 162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h> 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h> 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h> 202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h> 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h> 232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h> 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 27ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#ifndef AAPT_VERSION 28ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski #define AAPT_VERSION "" 29ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#endif 30ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info. All the cool kids do it. 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle) 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 0) { 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("(ignoring extra arguments)\n"); 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 39ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n"); 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only. The call fails if the file doesn't exist. 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName) 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip; 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, ZipFile::kOpenReadOnly); 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' not found\n", fileName); 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == PERMISSION_DENIED) { 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileName); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write. The file will be created if it doesn't 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set. 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate) 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int flags; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags = ZipFile::kOpenReadWrite; 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (okayToCreate) { 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags |= ZipFile::kOpenCreate; 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, flags); 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = NULL; 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method. 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method) 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (method == ZipEntry::kCompressStored) { 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Stored"; 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (method == ZipEntry::kCompressDeflated) { 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Deflated"; 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Unknown"; 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression). 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen) 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!uncompressedLen) { 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing. 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip" 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command. 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle) 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ZipEntry* entry; 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long totalUncLen, totalCompLen; 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 1) { 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: specify zip file name (only)\n"); 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadOnly(zipFileName); 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int count, i; 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Archive: %s\n", zipFileName); 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen = totalCompLen = 0; 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski count = zip->getNumEntries(); 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i = 0; i < count; i++) { 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByIndex(i); 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char dateBuf[32]; 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time_t when; 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski when = entry->getModWhen(); 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localtime(&when)); 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getUncompressedLen(), 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compressionName(entry->getCompressionMethod()), 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getCompressedLen(), 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(entry->getUncompressedLen(), 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCompressedLen()), 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (size_t) entry->getLFHOffset(), 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dateBuf, 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCRC32(), 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getFileName()); 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", entry->getFileName()); 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen += entry->getUncompressedLen(); 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen += entry->getCompressedLen(); 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------- --- -------\n"); 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %7ld %2d%% %d files\n", 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen, 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen, 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(totalUncLen, totalCompLen), 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->getNumEntries()); 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getAndroidList()) { 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(zipFileName), NULL)) { 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo resource table found.\n"); 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nResource table:\n"); 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(false); 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t N = tree.getAttributeCount(); 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeNameResID(i) == attrRes) { 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (ssize_t)i; 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return -1; 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiString8 getAttribute(const ResXMLTree& tree, const char* ns, 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* attr, String8* outError) 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = tree.indexOfAttribute(ns, attr); 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8* outError, int32_t defValue = -1) 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not an integer value"; 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree, 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrRes, String8* outError, int32_t defValue = -1) 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE) { 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(&value, 0); 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not an integer value"; 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defValue; 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree, 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrRes, String8* outError) 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType == Res_value::TYPE_STRING) { 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint16_t* str = tree.getAttributeStringValue(idx, &len); 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(&value, 0); 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute is not a string value"; 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String8(); 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Res_value* value2 = &value; 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len); 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return str ? String8(str, len) : String8(); 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable, 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResXMLTree& tree, uint32_t attrRes, String8* outError) 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx < 0) { 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "attribute could not be found"; 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.getAttributeValue(idx, value) != NO_ERROR) { 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value->dataType == Res_value::TYPE_REFERENCE) { 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resTable->resolveReference(value, 0); 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // The attribute was found and was resolved if need be. 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError != NULL) { 385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outError = "error getting resolved resource attribute"; 386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38976327314d2238e105f8b94909f9c0cf85caca318Maurice Chustatic void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree, 39076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu uint32_t attrRes, String8 attrLabel, String8* outError) 39176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 39276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 39376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError); 39476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 39576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 39676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 39776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 39876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 39976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8 result = getResolvedAttribute(resTable, tree, attrRes, outError); 4002675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 4012675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 40276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 40376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 40476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 40576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 40676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 40776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 40876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 40976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 416a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 4179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 4189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 41994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 441caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski INSTALL_LOCATION_ATTR = 0x010102b7, 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 4490a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4522675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 4612675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4632675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4669cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 4849cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4859cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4869cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4879cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 4889cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4899cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t screenSize = getIntegerAttribute(tree, 492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR, NULL, -1); 493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t screenDensity = getIntegerAttribute(tree, 494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR, NULL, -1); 495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 50758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) { 50858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 50958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 51058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 51158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 51258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 51358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 51458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 51558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 51658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 51758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 51858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 51958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 52058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 52158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 52258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 52358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 52458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) { 52558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-implied-permission: name='%s' reason='%s'\n", 52658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string(), 52758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(reason.string()).string()); 52858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 52958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 53094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, 53194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 53294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 53394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 53494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 53594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 53694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 53794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 53894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 53994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 54094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 54194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 54294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 54394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 54494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 54594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 54694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 54794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 54894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 54994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 55094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 55194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 55294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 55394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 5549cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 5559cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 5569cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 5579cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 5589cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 5599cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 56094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 56194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 56294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 56394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 56494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 56594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 56694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 5679cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 5689cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 5699cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 5709cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 5719cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 5729cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 57394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 57494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 57594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 57694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 57794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 57894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 57994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 58094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 category = getAttribute(tree, CATEGORY_ATTR, &error); 58194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 58294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 58394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 58494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 58694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 58794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 58994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 59094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 59194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 59294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 59394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 59494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 5959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 5969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 5979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 5989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 5992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 6002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to 6012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason. 6022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature { 6042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Name of the implied feature. 6062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name; 6082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * List of human-readable reasons for why this feature was implied. 6112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski SortedVector<String8> reasons; 6132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 6142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 6162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml 6172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup { 619d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup() : openGLESVersion(-1) {} 620d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 6212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Human readable label 6232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 label; 6252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 6272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Explicit features defined in the group 6282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 6292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, bool> features; 630d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 631d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski /** 632d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski * OpenGL ES version required 633d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski */ 634d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int openGLESVersion; 6352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 6362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures, 6382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const char* name, const char* reason) { 6392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name8(name); 6402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ssize_t idx = impliedFeatures->indexOfKey(name8); 6412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (idx < 0) { 6422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski idx = impliedFeatures->add(name8, ImpliedFeature()); 6432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).name = name8; 6442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).reasons.add(String8(reason)); 6462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 6472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp, 6492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) { 6502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("feature-group: label='%s'\n", grp.label.string()); 6512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 652d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (grp.openGLESVersion > 0) { 653d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski printf(" uses-gl-es: '0x%x'\n", grp.openGLESVersion); 654d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 655d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 6562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatures = grp.features.size(); 6572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatures; i++) { 6582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features[i]) { 6592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 6602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const String8& featureName = grp.features.keyAt(i); 6632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", 6642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ResTable::normalizeForOutput(featureName.string()).string()); 6652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numImpliedFeatures = 6682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski (impliedFeatures != NULL) ? impliedFeatures->size() : 0; 6692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numImpliedFeatures; i++) { 6702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i); 6712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(impliedFeature.name) >= 0) { 6722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // The feature is explicitly set, no need to use implied 6732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // definition. 6742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 6752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 printableFeatureName(ResTable::normalizeForOutput( 6782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeature.name.string())); 6792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", printableFeatureName.string()); 6802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-implied-feature: name='%s' reason='", 6812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printableFeatureName.string()); 6822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numReasons = impliedFeature.reasons.size(); 6832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numReasons; j++) { 6842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("%s", impliedFeature.reasons[j].string()); 6852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (j + 2 < numReasons) { 6862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", "); 6872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (j + 1 < numReasons) { 6882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", and "); 6892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("'\n"); 6922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 6942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) { 6962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (name == "android.hardware.camera.autofocus" || 6972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.camera.flash") { 6982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.camera"), true); 6992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.location.gps" || 7002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.location.network") { 7012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.location"), true); 7022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 7032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 7042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct") { 7052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen.multitouch"), true); 7062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 707d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else if (name == "android.hardware.opengles.aep") { 708d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski const int openGLESVersion31 = 0x00030001; 709d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (openGLESVersion31 > grp->openGLESVersion) { 710d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp->openGLESVersion = openGLESVersion31; 711d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 7122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 7132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 7142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 737f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 74991447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 760c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 76663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 76725e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (res.getError() != NO_ERROR) { 76825e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 76963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 77063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski } 77163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 7722cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // The dynamicRefTable can be null if there are no resources for this asset cookie. 7732cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // This fine. 77463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 77663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski Asset* asset = NULL; 77763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 79563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 79663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 82263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 84063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); 841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 84663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 8679cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 8689cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 8699cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 8709cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 8719cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 8729cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg = getAttribute(tree, NULL, "package", NULL); 8802675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "permission") { 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 8882675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("permission: %s\n", 8892675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "uses-permission") { 891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 89758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 89858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0, 89958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1)); 900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 9250a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 928ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 9292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski bool withinFeatureGroup = false; 930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 9329d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 9389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 9399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 942a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 943a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 945a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 94694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 9479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 9489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 9499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 9509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 9519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 952eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 9539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 956a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 959a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 960a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 96194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 96294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 9639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 9649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 965eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 9669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 9679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 9689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 96994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 97094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 971a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 972a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 973a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 974a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 976a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 977a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 97894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 9799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 9809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 981eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 997e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If an app declares itself as multiArch, we report the 998e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // native libraries differently. 999e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool hasMultiArch = false; 1000e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 10062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 10300a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 1033ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 10342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 10352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup commonFeatures; 10362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski Vector<FeatureGroup> featureGroups; 10372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, ImpliedFeature> impliedFeatures; 10382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 1043ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 1044ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 1045ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 1046ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 10472675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 10482675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 1049ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 1050ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 1051ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1052ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 1053ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1054ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1055ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.clear(); 1056ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1058ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = false; 10592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = false; 1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 3) { 10610a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (withinActivity && isMainActivity) { 10622675f769673f69b0661ddee346292f25cb30a296Maurice Chu String8 aName(getComponentName(pkg, activityName)); 10630a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLauncherActivity) { 10640a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("launchable-activity:"); 10659eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 10669eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 10679eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 10680a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 10690a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s'\n", 10709eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 10719eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string()); 10720a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 10730a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLeanbackLauncherActivity) { 10740a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("leanback-launchable-activity:"); 10759eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 10769eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 10779eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 10780a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 10790a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s' banner='%s'\n", 10809eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityLabel.string()).string(), 10819eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityIcon.string()).string(), 10829eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(activityBanner.string()).string()); 1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasIntentFilter) { 1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherActivities |= withinActivity; 1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherReceivers |= withinReceiver; 1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherServices |= withinService; 108994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 109094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (withinService) { 109194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && 109294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 109394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && 109494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 109594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 11009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 11020a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; 1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 4) { 1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinIntentFilter) { 1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinActivity) { 1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMainActivity |= actMainActivity; 11079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasLauncher |= catLauncher; 11089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraActivity |= actCamera; 11099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraSecureActivity |= actCameraSecure; 11109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; 1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinReceiver) { 1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWidgetReceivers |= actWidgetReceivers; 1113a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasDeviceAdminReceiver |= (actDeviceAdminEnabled && 1114a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission); 1115a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); 1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinService) { 1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasImeService |= actImeService; 1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWallpaperService |= actWallpaperService; 1119a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasAccessibilityService |= (actAccessibilityService && 1120a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission); 1121a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasPrintService |= (actPrintService && hasBindPrintServicePermission); 11229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasNotificationListenerService |= actNotificationListenerService && 11239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission; 1124eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasDreamService |= actDreamService && hasBindDreamServicePermission; 1125a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherServices |= (!actImeService && !actWallpaperService && 112694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski !actAccessibilityService && !actPrintService && 11279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actHostApduService && !actOffHostApduService && 11289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actNotificationListenerService); 11299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 11309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; 1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinIntentFilter = false; 1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 1138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 11419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski 11429cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 11439cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 11449cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 11459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 11469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 11479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d, %s\n", depth, tag.string()); 1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pkg = getAttribute(tree, NULL, "package", NULL); 11552675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: name='%s' ", 11562675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(pkg.string()).string()); 1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error); 1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string()); 1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (versionCode > 0) { 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='%d' ", versionCode); 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='' "); 1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error); 1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); 1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 117225d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("versionName='%s'", 11732675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(versionName.string()).string()); 117425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski 117525d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski String8 splitName = getAttribute(tree, NULL, "split", NULL); 117625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski if (!splitName.isEmpty()) { 117725d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf(" split='%s'", ResTable::normalizeForOutput( 117825d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski splitName.string()).string()); 117925d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski } 118025d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("\n"); 1181caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1182caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski int32_t installLocation = getResolvedIntegerAttribute(&res, tree, 1183caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski INSTALL_LOCATION_ATTR, &error, -1); 1184caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (error != "") { 1185caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n", 1186caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski error.string()); 1187caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1188caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1189caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1190caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (installLocation >= 0) { 1191caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("install-location:'"); 1192caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski switch (installLocation) { 1193caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 0: 1194caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("auto"); 1195caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1196caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 1: 1197caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("internalOnly"); 1198caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1199caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 2: 1200caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("preferExternal"); 1201caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1202caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski default: 1203caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "Invalid installLocation %d\n", installLocation); 1204caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1205caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1206caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("'\n"); 1207caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2) { 1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "application") { 1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = true; 1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 label; 1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setLocale(localeStr != NULL ? localeStr : ""); 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (llabel != "") { 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 12222675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-label:'%s'\n", 12232675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (label == "") { 1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-label-%s:'%s'\n", localeStr, 12292675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config tmpConfig = config; 1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tmpConfig.density = densities[i]; 1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(tmpConfig); 1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (icon != "") { 12412675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-icon-%d:'%s'\n", densities[i], 12422675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(icon.string()).string()); 1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); 1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0); 1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string()); 1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 12572675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application: label='%s' ", 12582675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(label.string()).string()); 12592675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("icon='%s'\n", ResTable::normalizeForOutput(icon.string()).string()); 1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (testOnly != 0) { 1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("testOnly='%d'\n", testOnly); 1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0); 1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string()); 1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (debuggable != 0) { 1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-debuggable\n"); 1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1272e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1273e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // We must search by name because the multiArch flag hasn't been API 1274e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // frozen yet. 1275e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, 1276e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski "multiArch"); 1277e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (multiArchIndex >= 0) { 1278e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski Res_value value; 1279e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) { 1280e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (value.dataType >= Res_value::TYPE_FIRST_INT && 1281e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski value.dataType <= Res_value::TYPE_LAST_INT) { 1282e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski hasMultiArch = value.data; 1283e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1284e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1285e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-sdk") { 1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); 1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error); 1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut") targetSdk = 4; 12972675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("sdkVersion:'%s'\n", 12982675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("sdkVersion:'%d'\n", code); 1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1); 1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != -1) { 1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("maxSdkVersion:'%d'\n", code); 1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error); 1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", 1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut" && targetSdk < 4) targetSdk = 4; 13172675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("targetSdkVersion:'%s'\n", 13182675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < code) { 1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("targetSdkVersion:'%d'\n", code); 1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-configuration") { 1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqTouchScreen = getIntegerAttribute(tree, 1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR, NULL, 0); 1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqKeyboardType = getIntegerAttribute(tree, 1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR, NULL, 0); 1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqHardKeyboard = getIntegerAttribute(tree, 1331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR, NULL, 0); 1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqNavigation = getIntegerAttribute(tree, 1333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR, NULL, 0); 1334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t reqFiveWayNav = getIntegerAttribute(tree, 1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR, NULL, 0); 1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-configuration:"); 1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqTouchScreen != 0) { 1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqTouchScreen='%d'", reqTouchScreen); 1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqKeyboardType != 0) { 1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqKeyboardType='%d'", reqKeyboardType); 1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqHardKeyboard != 0) { 1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqHardKeyboard='%d'", reqHardKeyboard); 1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqNavigation != 0) { 1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqNavigation='%d'", reqNavigation); 1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqFiveWayNav != 0) { 1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqFiveWayNav='%d'", reqFiveWayNav); 1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1353ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "supports-input") { 1354ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = true; 1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-screens") { 1356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = getIntegerAttribute(tree, 1357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR, NULL, 1); 1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = getIntegerAttribute(tree, 1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR, NULL, 1); 1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = getIntegerAttribute(tree, 1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR, NULL, 1); 1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = getIntegerAttribute(tree, 1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR, NULL, 1); 1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = getIntegerAttribute(tree, 1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR, NULL, 1); 1366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski requiresSmallestWidthDp = getIntegerAttribute(tree, 1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0); 1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatibleWidthLimitDp = getIntegerAttribute(tree, 1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0); 1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largestWidthLimitDp = getIntegerAttribute(tree, 1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0); 13722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (tag == "feature-group") { 13732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = true; 13742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup group; 13752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski group.label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 13762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (error != "") { 13772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski fprintf(stderr, "ERROR getting 'android:label' attribute:" 13782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski " %s\n", error.string()); 13792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski goto bail; 13802c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 13812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski featureGroups.add(group); 13822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-feature") { 1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int req = getIntegerAttribute(tree, 1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR, NULL, 1); 1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 13892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski commonFeatures.features.add(name, req); 13902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (req) { 13912c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addParentFeatures(&commonFeatures, name); 1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int vers = getIntegerAttribute(tree, 1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR, &error); 1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error == "") { 1397d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > commonFeatures.openGLESVersion) { 1398d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.openGLESVersion = vers; 1399d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-permission") { 1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "android.permission.CAMERA") { 1406d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.camera", 14072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_FINE_LOCATION") { 14102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.gps", 14112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 14132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 14142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { 14172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 14182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { 14212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location.network", 14222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 14242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 14252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || 1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.INSTALL_LOCATION_PROVIDER") { 14292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.location", 14302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.BLUETOOTH" || 1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.BLUETOOTH_ADMIN") { 14342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (targetSdk > 4) { 14352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 14362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 14382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", 14392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "targetSdkVersion > 4"); 14402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.RECORD_AUDIO") { 14422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.microphone", 14432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.ACCESS_WIFI_STATE" || 1446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_STATE" || 1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { 14482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.wifi", 14492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8::format("requested %s permission", name.string()) 14502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski .string()); 1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.CALL_PHONE" || 1452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.CALL_PRIVILEGED" || 1453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.MODIFY_PHONE_STATE" || 1454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.PROCESS_OUTGOING_CALLS" || 1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.READ_SMS" || 1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_SMS" || 1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_MMS" || 1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.RECEIVE_WAP_PUSH" || 1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.SEND_SMS" || 1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_APN_SETTINGS" || 1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name == "android.permission.WRITE_SMS") { 14622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.telephony", 14632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8("requested a telephony permission").string()); 1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { 1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { 1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadExternalStoragePermission = true; 1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_PHONE_STATE") { 1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadPhoneStatePermission = true; 1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CONTACTS") { 1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadContactsPermission = true; 1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CONTACTS") { 1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteContactsPermission = true; 1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.READ_CALL_LOG") { 1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasReadCallLogPermission = true; 1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (name == "android.permission.WRITE_CALL_LOG") { 1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteCallLogPermission = true; 1478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 147958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 148058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 148158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0, 148258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1)); 148358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } else { 1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-package") { 1489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 14912675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("uses-package:'%s'\n", 14922675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "original-package") { 1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 15012675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("original-package:'%s'\n", 15022675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-gl-texture") { 1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 15112675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("supports-gl-texture:'%s'\n", 15122675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "compatible-screens") { 15199cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski printCompatibleScreens(tree, &error); 15209cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (error != "") { 15219cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR getting compatible screens: %s\n", 15229cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski error.string()); 15239cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 15249cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "package-verifier") { 1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error); 1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (publicKey != "" && error == "") { 1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("package-verifier: name='%s' publicKey='%s'\n", 15322675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string(), 15332675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(publicKey.string()).string()); 1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1537ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (depth == 3) { 1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 15419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 154394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory = false; 154494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory = false; 154594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindDeviceAdminPermission = false; 154694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindInputMethodPermission = false; 154794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindAccessibilityServicePermission = false; 154894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindPrintServicePermission = false; 154994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = false; 15509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes = false; 15519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = false; 1552eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = false; 1553ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinApplication) { 1554ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if(tag == "activity") { 1555ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinActivity = true; 1556ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityName = getAttribute(tree, NAME_ATTR, &error); 1557ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1558ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1559ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1560ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1561ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1563ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 1564ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1565ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", 1566ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1567ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1568ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1570ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 1571ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1572ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", 1573ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1574ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1575ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 15770a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error); 15780a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (error != "") { 15790a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", 15800a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn error.string()); 15810a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn goto bail; 15820a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 15830a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn 1584ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright int32_t orien = getResolvedIntegerAttribute(&res, tree, 1585ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright SCREEN_ORIENTATION_ATTR, &error); 1586ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error == "") { 1587ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (orien == 0 || orien == 6 || orien == 8) { 1588ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests landscape, sensorLandscape, or reverseLandscape. 15892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape", 15902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a landscape orientation"); 1591ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (orien == 1 || orien == 7 || orien == 9) { 1592ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests portrait, sensorPortrait, or reversePortrait. 15932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait", 15942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "one or more activities have specified a portrait orientation"); 1595ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1597ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "uses-library") { 1598ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright String8 libraryName = getAttribute(tree, NAME_ATTR, &error); 1599ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1600ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1601ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for uses-library" 1602ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1603ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1604ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1605ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright int req = getIntegerAttribute(tree, 1606ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright REQUIRED_ATTR, NULL, 1); 1607ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("uses-library%s:'%s'\n", 16082675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", ResTable::normalizeForOutput( 16092675f769673f69b0661ddee346292f25cb30a296Maurice Chu libraryName.string()).string()); 1610ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "receiver") { 1611ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinReceiver = true; 1612ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright receiverName = getAttribute(tree, NAME_ATTR, &error); 1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1614ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1615ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, 1616ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for receiver:" 1617ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright " %s\n", error.string()); 1618ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1619ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1620a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1621a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 permission = getAttribute(tree, PERMISSION_ATTR, &error); 1622a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1623a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_DEVICE_ADMIN") { 1624a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission = true; 1625a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1626a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1627a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1628a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " receiver '%s': %s\n", receiverName.string(), error.string()); 1629a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1630ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "service") { 1631ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinService = true; 1632ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright serviceName = getAttribute(tree, NAME_ATTR, &error); 1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1634ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1635ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1636ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "service:%s\n", error.string()); 1637ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1638ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1639a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1640a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 permission = getAttribute(tree, PERMISSION_ATTR, &error); 1641a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1642a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_INPUT_METHOD") { 1643a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindInputMethodPermission = true; 1644a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") { 1645a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission = true; 1646a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (permission == "android.permission.BIND_PRINT_SERVICE") { 1647a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindPrintServicePermission = true; 164894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (permission == "android.permission.BIND_NFC_SERVICE") { 164994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = true; 16509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { 16519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = true; 1652eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (permission == "android.permission.BIND_DREAM_SERVICE") { 1653eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = true; 1654a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1655a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 1656a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for" 1657a5018c900f126ee8424c82497f32983873db741bAdam Lesinski " service '%s': %s\n", serviceName.string(), error.string()); 1658a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 16599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (tag == "provider") { 16609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = true; 16619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error); 16639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 16649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:" 16659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 16669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 16679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree, 16709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR, &error); 16719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 16729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:" 16739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 16749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 16759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error); 16789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 16799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:" 16809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski " %s\n", error.string()); 16819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 16829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 16839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 16849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes |= exported && grantUriPermissions && 16859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski permission == "android.permission.MANAGE_DOCUMENTS"; 16869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1687ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (bundle->getIncludeMetaData() && tag == "meta-data") { 1688b71adb6571aa740f4fa794602133f708e1b96545Adam Lesinski String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error); 1689ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 1690ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute for " 1691ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "meta-data:%s\n", error.string()); 1692ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1693ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 16942675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("meta-data: name='%s' ", 16952675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(metaDataName.string()).string()); 169676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"), 169776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu &error); 1698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 169976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu // Try looking for a RESOURCE_ATTR 170076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu error = ""; 170176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR, 170276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8("resource"), &error); 1703ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 170476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu fprintf(stderr, "ERROR getting 'android:value' or " 170576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "'android:resource' attribute for " 170676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "meta-data:%s\n", error.string()); 1707ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1708ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1709ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 171076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("\n"); 1711ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (withinSupportsInput && tag == "input-type") { 1712ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright String8 name = getAttribute(tree, NAME_ATTR, &error); 1713ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (name != "" && error == "") { 1714ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.add(name); 1715ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1716ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1717ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 17212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (withinFeatureGroup && tag == "uses-feature") { 1722d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup& top = featureGroups.editTop(); 1723d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 17242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name = getResolvedAttribute(&res, tree, NAME_ATTR, &error); 1725d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (name != "" && error == "") { 1726d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski top.features.add(name, true); 1727d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski addParentFeatures(&top, name); 1728d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else { 1729d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int vers = getIntegerAttribute(tree, GL_ES_VERSION_ATTR, &error); 1730d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (error == "") { 1731d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > top.openGLESVersion) { 1732d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski top.openGLESVersion = vers; 1733d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1734d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 17352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1736a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 173794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 4) { 173894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "intent-filter") { 173994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasIntentFilter = true; 174094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinIntentFilter = true; 174194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actMainActivity = false; 174294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWidgetReceivers = false; 174394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actImeService = false; 174494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWallpaperService = false; 174594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actAccessibilityService = false; 174694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actPrintService = false; 174794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actDeviceAdminEnabled = false; 174894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = false; 174994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = false; 17509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = false; 17519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = false; 1752eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = false; 17539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = false; 17549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = false; 17559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = false; 175694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (withinService && tag == "meta-data") { 175794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 name = getAttribute(tree, NAME_ATTR, &error); 175894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 175994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute for" 176094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 176194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 176294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 176394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 176494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service" || 176594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski name == "android.nfc.cardemulation.off_host_apdu_service") { 176694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool offHost = true; 176794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service") { 176894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost = false; 176994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 177094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 177194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error); 177294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 177394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting 'android:resource' attribute for" 177494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); 177594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 177694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 177794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 177894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories = getNfcAidCategories(assets, xmlPath, 177994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost, &error); 178094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 178194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski fprintf(stderr, "ERROR getting AID category for service '%s'\n", 178294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski serviceName.string()); 178394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 178494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 178594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 178694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const size_t catLen = categories.size(); 178794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski for (size_t i = 0; i < catLen; i++) { 178894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool paymentCategory = (categories[i] == "payment"); 178994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (offHost) { 179094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory |= paymentCategory; 179194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 179294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory |= paymentCategory; 179394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 179494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 179594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 179694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1797a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if ((depth == 5) && withinIntentFilter) { 1798a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 action; 1799a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "action") { 1800a5018c900f126ee8424c82497f32983873db741bAdam Lesinski action = getAttribute(tree, NAME_ATTR, &error); 1801a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1802a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", 1803a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1804a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1805a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1806a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1807a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1808a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.MAIN") { 1809a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isMainActivity = true; 1810a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actMainActivity = true; 18119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA" || 18129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski action == "android.media.action.VIDEO_CAMERA") { 18139d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = true; 18149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") { 18159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = true; 1816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1817a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinReceiver) { 1818a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 1819a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWidgetReceivers = true; 1820a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") { 1821a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actDeviceAdminEnabled = true; 1822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1823a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinService) { 1824a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.view.InputMethod") { 1825a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actImeService = true; 1826a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.service.wallpaper.WallpaperService") { 1827a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWallpaperService = true; 1828a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.accessibilityservice.AccessibilityService") { 1829a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actAccessibilityService = true; 1830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.printservice.PrintService") { 1831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actPrintService = true; 183294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { 183394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = true; 183494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { 183594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = true; 18369d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.service.notification.NotificationListenerService") { 18379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = true; 1838eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (action == "android.service.dreams.DreamService") { 1839eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = true; 18409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18419d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 18429d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (action == "android.content.action.DOCUMENTS_PROVIDER") { 18439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = true; 1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1846a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.SEARCH") { 1847a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isSearchable = true; 1848a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1849a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1851a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "category") { 1852a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 category = getAttribute(tree, NAME_ATTR, &error); 1853a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 1854a5018c900f126ee8424c82497f32983873db741bAdam Lesinski fprintf(stderr, "ERROR getting 'name' attribute: %s\n", 1855a5018c900f126ee8424c82497f32983873db741bAdam Lesinski error.string()); 1856a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1857a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1858a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1859a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (category == "android.intent.category.LAUNCHER") { 1860a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isLauncherActivity = true; 18610a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } else if (category == "android.intent.category.LEANBACK_LAUNCHER") { 18620a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isLeanbackLauncherActivity = true; 18639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (category == "android.intent.category.HOME") { 18649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = true; 1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-1.6 implicitly granted permission compatibility logic 1872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 4) { 1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteExternalStoragePermission) { 187458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE")); 187558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"), 187658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadPhoneStatePermission) { 188058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_PHONE_STATE")); 188158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"), 188258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the application has requested WRITE_EXTERNAL_STORAGE, we will 1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // force them to always take READ_EXTERNAL_STORAGE as well. We always 1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // do this (regardless of target API version) because we can't have 1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // an app with write permission but not read permission. 1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { 189158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE")); 189258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 189358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("requested WRITE_EXTERNAL_STORAGE")); 1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-JellyBean call log permission compatibility. 1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 16) { 1898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadCallLogPermission && hasReadContactsPermission) { 189958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_CALL_LOG")); 190058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"), 190158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested READ_CONTACTS")); 1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteCallLogPermission && hasWriteContactsPermission) { 190458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_CALL_LOG")); 190558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"), 190658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested WRITE_CONTACTS")); 1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen", 19112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski "default feature for all apps"); 19122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 19132c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatureGroups = featureGroups.size(); 19142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (numFeatureGroups == 0) { 19152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // If no <feature-group> tags were defined, apply auto-implied features. 19162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(commonFeatures, &impliedFeatures); 19172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 19182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else { 19192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // <feature-group> tags are defined, so we ignore implied features and 19202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatureGroups; i++) { 19212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup& grp = featureGroups.editItemAt(i); 19222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1923d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (commonFeatures.openGLESVersion > grp.openGLESVersion) { 1924d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.openGLESVersion = commonFeatures.openGLESVersion; 1925d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1926d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 19272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // Merge the features defined in the top level (not inside a <feature-group>) 19282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // with this feature group. 19292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numCommonFeatures = commonFeatures.features.size(); 19302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numCommonFeatures; j++) { 19312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) { 1932d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.features.add(commonFeatures.features.keyAt(j), 1933d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.features[j]); 19342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (!grp.features.isEmpty()) { 19382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(grp); 19392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWidgetReceivers) { 19459d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("app-widget"); 1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1947a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasDeviceAdminReceiver) { 19489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("device-admin"); 1949a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasImeService) { 19519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("ime"); 1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWallpaperService) { 19549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("wallpaper"); 1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1956a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasAccessibilityService) { 19579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("accessibility"); 1958a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1959a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasPrintService) { 19609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("print-service"); 1961a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 196294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (hasPaymentService) { 19639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("payment"); 19649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (isSearchable) { 19669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("search"); 19679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasDocumentsProvider) { 19699d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("document-provider"); 19709d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19719d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasLauncher) { 19729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("launcher"); 19739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasNotificationListenerService) { 19759d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("notification-listener"); 19769d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 1977eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock if (hasDreamService) { 1978eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock printComponentPresence("dream"); 1979eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } 19809d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraActivity) { 19819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera"); 19829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraSecureActivity) { 19849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera-secure"); 19859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 19869d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 19879d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasMainActivity) { 19889d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("main\n"); 198994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherActivities) { 1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-activities\n"); 1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 19939d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasOtherReceivers) { 1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-receivers\n"); 1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherServices) { 1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-services\n"); 1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For modern apps, if screen size buckets haven't been specified 2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but the new width ranges have, then infer the buckets from them. 2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && requiresSmallestWidthDp > 0) { 2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatWidth = compatibleWidthLimitDp; 2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatWidth <= 0) { 2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatWidth = requiresSmallestWidthDp; 2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { 2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = -1; 2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = 0; 2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { 2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = 0; 2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { 2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = -1; 2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = 0; 2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { 2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = -1; 2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = 0; 2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Determine default values for any unspecified screen sizes, 2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // based on the target SDK of the package. As of 4 (donut) 2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the screen size support was introduced, so all default to 2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // enabled. 2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0) { 2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = targetSdk >= 4 ? -1 : 0; 2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen > 0) { 2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen > 0) { 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = targetSdk >= 4 ? -1 : 0; 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen > 0) { 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Introduced in Gingerbread. 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = targetSdk >= 9 ? -1 : 0; 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (anyDensity > 0) { 2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || compatibleWidthLimitDp > 0) ? -1 : 0; 2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-screens:"); 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen != 0) { 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'small'"); 2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen != 0) { 2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'normal'"); 2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen != 0) { 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'large'"); 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen != 0) { 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'xlarge'"); 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); 2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp > 0) { 2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); 2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatibleWidthLimitDp > 0) { 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largestWidthLimitDp > 0) { 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("largest-width-limit:'%d'\n", largestWidthLimitDp); 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("locales:"); 2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localeStr = "--_--"; 2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'", localeStr); 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("densities:"); 2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%d'", densities[i]); 2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir != NULL) { 2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir->getFileCount() > 0) { 2097e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski SortedVector<String8> architectures; 2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<dir->getFileCount(); i++) { 2099e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.add(ResTable::normalizeForOutput( 2100e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski dir->getFileName(i).string())); 2101e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2102e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2103e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool outputAltNativeCode = false; 2104e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // A multiArch package is one that contains 64-bit and 2105e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit versions of native code and expects 3rd-party 2106e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // apps to load these native code libraries. Since most 2107e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 64-bit systems also support 32-bit apps, the apps 2108e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // loading this multiArch package's code may be either 2109e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit or 64-bit. 2110e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (hasMultiArch) { 2111e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If this is a multiArch package, report the 64-bit 2112e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // version only. Then as a separate entry, report the 2113e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // rest. 2114e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 2115e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If we report the 32-bit architecture, this APK will 2116e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // be installed on a 32-bit device, causing a large waste 2117e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // of bandwidth and disk space. This assumes that 2118e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // the developer of the multiArch package has also 2119e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // made a version that is 32-bit only. 2120e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 intel64("x86_64"); 2121e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 arm64("arm64-v8a"); 2122e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski ssize_t index = architectures.indexOf(intel64); 2123e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index < 0) { 2124e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski index = architectures.indexOf(arm64); 2125e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2126e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2127e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index >= 0) { 2128e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code: '%s'\n", architectures[index].string()); 2129e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.removeAt(index); 2130e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski outputAltNativeCode = true; 2131e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2132e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2133e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2134e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski const size_t archCount = architectures.size(); 2135e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (archCount > 0) { 2136e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (outputAltNativeCode) { 2137e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("alt-"); 2138e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2139e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code:"); 2140e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski for (size_t i = 0; i < archCount; i++) { 2141e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf(" '%s'", architectures[i].string()); 2142e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2143e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("\n"); 2144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete dir; 2147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badger", option) == 0) { 2149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s", CONSOLE_DATA); 2150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("configurations", option) == 0) { 2151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 2152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 2153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = configs.size(); 2154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", configs[i].toString().string()); 2156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 2159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset) { 2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive. 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle) 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getUpdate()) { 2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* avoid confusion */ 2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: can't use '-u' with add\n"); 2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, true); 2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'... (from gzip)\n", fileName); 2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getJunkPath()) { 2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 storageName = String8(fileName).getPathLeaf(); 22152675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s' as '%s'...\n", fileName, 22162675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(storageName.string()).string()); 2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, storageName.string(), 2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getCompressionMethod(), NULL); 2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'...\n", fileName); 2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": file not found\n"); 2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == ALREADY_EXISTS) { 2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": already exists in archive\n"); 2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "\n"); 2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive. 2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle) 2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, false); 2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName); 2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipEntry* entry; 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByName(fileName); 2277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry == NULL) { 2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s' NOT FOUND\n", fileName); 2279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->remove(entry); 2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to delete '%s' from '%s'\n", 2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getFileSpecEntry(i), zipFileName); 2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* update the archive */ 2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->flush(); 2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22993921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) { 2300fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numDirs = dir->getDirs().size(); 2301fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numDirs; i++) { 23023921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski bool ignore = ignoreConfig; 23033921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); 23043921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const char* dirStr = subDir->getLeaf().string(); 23053921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (!ignore && strstr(dirStr, "mipmap") == dirStr) { 23063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski ignore = true; 23073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 23083921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = addResourcesToBuilder(subDir, builder, ignore); 2309fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2310fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2311fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2312fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2313fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2314fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numFiles = dir->getFiles().size(); 2315fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numFiles; i++) { 2316fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<AaptGroup> gp = dir->getFiles().valueAt(i); 2317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numConfigs = gp->getFiles().size(); 2318fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t j = 0; j < numConfigs; j++) { 23193921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = NO_ERROR; 23203921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (ignoreConfig) { 23213921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 23223921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } else { 23233921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 23243921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 2325fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2326fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Failed to add %s (%s) to builder.\n", 2327fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); 2328fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2329fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2330fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2331fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2332fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 2333fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2334fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2335fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) { 2336fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (split->isBase()) { 2337fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return original; 2338fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2339fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2340fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 ext(original.getPathExtension()); 2341fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (ext == String8(".apk")) { 2342fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s%s", 2343fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski original.getBasePath().string(), 2344fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string(), 2345fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ext.string()); 2346fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2347fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2348fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s", original.string(), 2349fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string()); 2350fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files. 2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle) 2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* outputAPKFile; 2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retVal = 1; 2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptAssets> assets; 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int N; 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FILE* fp; 2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 dependencyFile; 2364fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<ApkBuilder> builder; 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2366a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // -c en_XA or/and ar_XB means do pseudolocalization 2367fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<WeakResourceFilter> configFilter = new WeakResourceFilter(); 2368fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = configFilter->parse(bundle->getConfigurations()); 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2372fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudo()) { 2373a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); 2374a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 2375fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudoBidi()) { 2376a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = bundle->getFileSpecCount(); 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 238109384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { 2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no input files\n"); 2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile = bundle->getOutputAPKFile(); 2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure the filenames provided exist and are of the appropriate type. 2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FileType type; 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = getFileType(outputAPKFile); 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "ERROR: output file '%s' exists but is not regular file\n", 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile); 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Load the assets. 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets = new AaptAssets(); 2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set up the resource gathering in assets if we're going to generate 2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dependency files. Every time we encounter a resource while slurping 2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the tree, we'll add it to these stores so we have full resource paths 2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to write to a dependency file. 2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> resPathStore = new FilePathStore; 2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullResPaths(resPathStore); 2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> assetPathStore = new FilePathStore; 2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullAssetPaths(assetPathStore); 2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = assets->slurpFromArgs(bundle); 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->print(String8()); 2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2423fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Create the ApkBuilder, which will collect the compiled files 2424fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // to write to the final APK (or sets of APKs if we are building 2425fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // a Split APK. 2426fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski builder = new ApkBuilder(configFilter); 2427fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2428fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If we are generating a Split APK, find out which configurations to split on. 2429fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (bundle->getSplitConfigurations().size() > 0) { 2430fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<String8>& splitStrs = bundle->getSplitConfigurations(); 2431fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splitStrs.size(); 2432fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2433fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::set<ConfigDescription> configs; 2434fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) { 2435fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string()); 2436fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2437fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2438fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2439fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = builder->createSplitForConfigs(configs); 2440fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2441fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2442fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2443fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2444fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2445fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If they asked for any fileAs that need to be compiled, do so. 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 2448fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = buildResources(bundle, assets, builder); 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != 0) { 2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At this point we've read everything and processed everything. From here 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // on out it's just writing output files. 2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update symbols with information about which ones are needed as Java symbols. 2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->applyJavaSymbols(); 2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, do that here 2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is the packaging step, generate the dependency file next to 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the output apk (e.g. bin/resources.ap_.d) 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(outputAPKFile); 2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add the .d extension to the dependency file. 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.append(".d"); 2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Else if this is the R.java dependency generation step, 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // generate the dependency file in the R.java package subdirectory 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java.d 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(bundle->getRClassDir()); 2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.appendPath("R.java.d"); 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure we have a clean dependency file to start with 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "w"); 2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out R.java constants 2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets->havePrivateSymbols()) { 2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getCustomPackage() == NULL) { 2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file into the appropriate class directory 2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java 2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), true); 2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 customPkg(bundle->getCustomPackage()); 2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, customPkg, true); 2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we have library files, we're going to write our R.java file into 2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the appropriate class directory for those libraries as well. 2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/lib/R.java 2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getExtraPackages() != NULL) { 2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Split on colon 2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 libs(bundle->getExtraPackages()); 2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); 2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (packageString != NULL) { 2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file out with the correct package name 2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, String8(packageString), true); 2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski packageString = strtok(NULL, ":"); 2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski libs.unlockBuffer(); 2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), false); 2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true); 2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out the ProGuard file 2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeProguardFile(bundle, assets); 2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the apk 2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2535fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Gather all resources and add them to the APK Builder. The builder will then 2536fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // figure out which Split they belong in. 2537fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = addResourcesToBuilder(assets, builder); 2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2541fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2542fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<sp<ApkSplit> >& splits = builder->getSplits(); 2543fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splits.size(); 2544fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2545fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const sp<ApkSplit>& split = splits[i]; 2546fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 outputPath = buildApkName(String8(outputAPKFile), split); 2547fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = writeAPK(bundle, outputPath, split); 2548fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2549fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string()); 2550fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2551fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2552fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, we need to finish up here. 2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the writeResourceSymbols and writeAPK functions have already written the target 2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // half of the dependency file, now we need to write the prerequisites. (files that 2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the R.java file or .ap_ file depend on) 2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now that writeResourceSymbols or writeAPK has taken care of writing 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the targets to our dependency file, we'll write the prereqs 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "a+"); 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " : "); 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool includeRaw = (outputAPKFile != NULL); 2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Also manually add the AndroidManifeset since it's not under res/ or assets/ 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and therefore was not added to our pathstores during slurping 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retVal = 0; 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos::printErrors(stderr); 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return retVal; 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -S flag points to a source directory containing drawable* folders 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -C flag points to destination directory. The folder structure in the 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * source directory will be mirrored to the destination (cache) directory 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Destination directory will be updated to match the PNG files in 25892675f769673f69b0661ddee346292f25cb30a296Maurice Chu * the source directory. 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle) 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching PNG Files in "); 2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); 2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); 2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski updatePreProcessedCache(bundle); 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -i points to a single png file 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -o points to a single png output file 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle) 2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); 2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); 2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 input(bundle->getSingleCrunchInputFile()); 2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 output(bundle->getSingleCrunchOutputFile()); 2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { 2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we can't return the status_t as it gets truncate to the lower 8 bits. 2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 42; 2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = { 2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, 2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, 2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, 2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, 2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, 2675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, 2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, 2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, 2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, 2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, 2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, 2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, 2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, 2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, 2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 2710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 2716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 2717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 2723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 2724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 2728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, 2731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, 2734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 2735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 2741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 2742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, 2745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 2746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, 2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 2751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, 2752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, 2753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 2756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 2757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 2758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 2759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 2760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, 2767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 2770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, 2771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 2774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 2775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 2777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 2778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 2782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 2787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 2788