1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Android Asset Packaging Tool main entry point. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include "AaptXml.h" 7fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "ApkBuilder.h" 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Bundle.h" 92c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Images.h" 102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include "Main.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Errors.h> 162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/KeyedVector.h> 172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/List.h> 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/SortedVector.h> 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/threads.h> 212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <utils/Vector.h> 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <errno.h> 242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski#include <fcntl.h> 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 266f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <iostream> 276f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <string> 286f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez#include <sstream> 296f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#ifndef AAPT_VERSION 33ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski #define AAPT_VERSION "" 34ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski#endif 35ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Show version info. All the cool kids do it. 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doVersion(Bundle* bundle) 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 0) { 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("(ignoring extra arguments)\n"); 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 44ad751224401564dcc8338df3d5c4c5de7722be8fAdam Lesinski printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n"); 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read only. The call fails if the file doesn't exist. 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadOnly(const char* fileName) 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip; 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, ZipFile::kOpenReadOnly); 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' not found\n", fileName); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == PERMISSION_DENIED) { 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileName); 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Open the file read-write. The file will be created if it doesn't 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * already exist and "okayToCreate" is set. 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns NULL on failure. 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiZipFile* openReadWrite(const char* fileName, bool okayToCreate) 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result; 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int flags; 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags = ZipFile::kOpenReadWrite; 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (okayToCreate) { 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags |= ZipFile::kOpenCreate; 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = new ZipFile; 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->open(fileName, flags); 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = NULL; 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return zip; 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a short string describing the compression method. 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst char* compressionName(int method) 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (method == ZipEntry::kCompressStored) { 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Stored"; 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (method == ZipEntry::kCompressDeflated) { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Deflated"; 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "Unknown"; 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return the percent reduction in size (0% == no compression). 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint calcPercent(long uncompressedLen, long compressedLen) 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!uncompressedLen) { 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "list" command, which can be a simple file dump or 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * a verbose listing. 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The verbose listing closely matches the output of the Info-ZIP "unzip" 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * command. 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doList(Bundle* bundle) 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ZipEntry* entry; 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long totalUncLen, totalCompLen; 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() != 1) { 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: specify zip file name (only)\n"); 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadOnly(zipFileName); 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int count, i; 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Archive: %s\n", zipFileName); 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen = totalCompLen = 0; 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski count = zip->getNumEntries(); 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i = 0; i < count; i++) { 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByIndex(i); 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char dateBuf[32]; 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time_t when; 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski when = entry->getModWhen(); 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localtime(&when)); 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getUncompressedLen(), 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compressionName(entry->getCompressionMethod()), 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (long) entry->getCompressedLen(), 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(entry->getUncompressedLen(), 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCompressedLen()), 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (size_t) entry->getLFHOffset(), 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dateBuf, 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getCRC32(), 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry->getFileName()); 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", entry->getFileName()); 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen += entry->getUncompressedLen(); 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen += entry->getCompressedLen(); 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf( 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "-------- ------- --- -------\n"); 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%8ld %7ld %2d%% %d files\n", 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalUncLen, 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski totalCompLen, 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski calcPercent(totalUncLen, totalCompLen), 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->getNumEntries()); 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getAndroidList()) { 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(zipFileName), NULL)) { 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo resource table found.\n"); 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nResource table:\n"); 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(false); 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 249ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, 25076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu uint32_t attrRes, String8 attrLabel, String8* outError) 25176327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 253ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError); 25476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 25576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 25676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 25776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 259ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError); 2602675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 2612675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 26276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 26676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 26776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 26876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 26976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 276a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 2779d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 2789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 27994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 301caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski INSTALL_LOCATION_ATTR = 0x010102b7, 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 30894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 3090a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 310d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn ISGAME_ATTR = 0x10103f4, 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3132675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3222675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3242675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 3459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 3469cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 3479cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 3489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 3499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 3509cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 352ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenSize = AaptXml::getIntegerAttribute(tree, 353ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_SIZE_ATTR); 354ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenDensity = AaptXml::getIntegerAttribute(tree, 355ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_DENSITY_ATTR); 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 36858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) { 36958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 37058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 37158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 37258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 37358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 37858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 37958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 38058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 38158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 38258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 38358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason) { 38658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-implied-permission: name='%s' reason='%s'\n", 38758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string(), 38858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(reason.string()).string()); 38958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 39058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 39194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam LesinskiVector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, 39294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 39394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 39494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 39594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 39694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 39794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 39894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 39994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 40194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 40394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 40494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 40694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 40794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 40894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 40994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 41094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 41194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 41294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 41394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 41494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 4159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4169cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4179cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4189cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4199cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4209cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 42194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 42394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 42494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 42594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 42794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 4289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4329cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4339cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 43494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 43694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 44094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 441ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error); 44294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 44394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 44494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 44594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 45194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 45294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 45394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 45494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 45594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 4569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 4579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 4589d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 4599d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 4602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to 4622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason. 4632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature { 4652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4662c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Name of the implied feature. 4672c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4682c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name; 4692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4702c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * List of human-readable reasons for why this feature was implied. 4722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski SortedVector<String8> reasons; 4742c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 4752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4772c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml 4782c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4792c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup { 480d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup() : openGLESVersion(-1) {} 481d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 4822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4832c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Human readable label 4842c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 label; 4862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Explicit features defined in the group 4892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4902c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, bool> features; 491d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 492d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski /** 493d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski * OpenGL ES version required 494d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski */ 495d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int openGLESVersion; 4962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures, 4992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const char* name, const char* reason) { 5002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name8(name); 5012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ssize_t idx = impliedFeatures->indexOfKey(name8); 5022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (idx < 0) { 5032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski idx = impliedFeatures->add(name8, ImpliedFeature()); 5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).name = name8; 5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeatures->editValueAt(idx).reasons.add(String8(reason)); 5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp, 5102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const KeyedVector<String8, ImpliedFeature>* impliedFeatures = NULL) { 5112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("feature-group: label='%s'\n", grp.label.string()); 5122c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 513d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (grp.openGLESVersion > 0) { 514d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski printf(" uses-gl-es: '0x%x'\n", grp.openGLESVersion); 515d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 516d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 5172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatures = grp.features.size(); 5182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatures; i++) { 51973a05114b051c6dcf5e5126ac94eaf8cac0ab289Adam Lesinski const bool required = grp.features[i]; 5202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const String8& featureName = grp.features.keyAt(i); 52273a05114b051c6dcf5e5126ac94eaf8cac0ab289Adam Lesinski printf(" uses-feature%s: name='%s'\n", (required ? "" : "-not-required"), 5232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ResTable::normalizeForOutput(featureName.string()).string()); 5242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numImpliedFeatures = 5272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski (impliedFeatures != NULL) ? impliedFeatures->size() : 0; 5282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numImpliedFeatures; i++) { 5292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i); 5302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(impliedFeature.name) >= 0) { 5312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // The feature is explicitly set, no need to use implied 5322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // definition. 5332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 5342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 printableFeatureName(ResTable::normalizeForOutput( 5372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeature.name.string())); 5382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-feature: name='%s'\n", printableFeatureName.string()); 5392c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(" uses-implied-feature: name='%s' reason='", 5402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printableFeatureName.string()); 5412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numReasons = impliedFeature.reasons.size(); 5422c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numReasons; j++) { 5432c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("%s", impliedFeature.reasons[j].string()); 5442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (j + 2 < numReasons) { 5452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", "); 5462c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (j + 1 < numReasons) { 5472c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", and "); 5482c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5502c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("'\n"); 5512c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5522c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5532c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5542c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) { 5552c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (name == "android.hardware.camera.autofocus" || 5562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.camera.flash") { 5572c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.camera"), true); 5582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.location.gps" || 5592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.location.network") { 5602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.location"), true); 5612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 5622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 5632c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct") { 5642c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen.multitouch"), true); 5652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), true); 566d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else if (name == "android.hardware.opengles.aep") { 567d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski const int openGLESVersion31 = 0x00030001; 568d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (openGLESVersion31 > grp->openGLESVersion) { 569d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp->openGLESVersion = openGLESVersion31; 570d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 5712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5732c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 596f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 60891447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 619c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; 620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&res == NULL) { 624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 62563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 62625e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski } else if (res.getError() != NO_ERROR) { 62725e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 62863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 62963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski } 63063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 6312cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // The dynamicRefTable can be null if there are no resources for this asset cookie. 6322cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // This fine. 63363e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); 634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski Asset* asset = NULL; 63663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#ifndef HAVE_ANDROID_OS 639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 65463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 65563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 68163e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 68763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 69963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); 700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70563e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 7269cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 7279cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 7289cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n"); 7299cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 7309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 7319cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 738ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 7392675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "permission") { 741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 742ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 7472675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("permission: %s\n", 7482675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2 && tag == "uses-permission") { 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 751ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s\n", error.string()); 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 75658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(name, 757ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 758ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 7840a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 787ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 7882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski bool withinFeatureGroup = false; 789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 7919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 7979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 7989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 801a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 802a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 804a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 80594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 8069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 8079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 8089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 8099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 8109d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 811eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 8129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 815a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 818a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 819a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 82094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 82194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 8229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 8239d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 824eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 8259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 8269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 8279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 82894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 82994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 830a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 831a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 832a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 833a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 834a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 835a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 836a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 83794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 8389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 8399d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 840eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 856e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If an app declares itself as multiArch, we report the 857e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // native libraries differently. 858e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool hasMultiArch = false; 859e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 8652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 8890a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 892ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 8932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 8942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup commonFeatures; 8952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski Vector<FeatureGroup> featureGroups; 8962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, ImpliedFeature> impliedFeatures; 8972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 902ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 903ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 904ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 905ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 9062675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 9072675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 908ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 909ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 910ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 911ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 912ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 913ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 914