Command.cpp revision cd154e95353e7af11314d2339500d6c7f85e181a
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 218ba3fe56edc1da4dad0d831a1892e7b1c3c20c437Elliott Hughes#ifdef __ANDROID__ 219b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe static const bool kHaveAndroidOs = true; 220b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe#else 221b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe static const bool kHaveAndroidOs = false; 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 223b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe const ResTable& res = assets.getResources(false); 224b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe if (!kHaveAndroidOs) { 225b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe printf("\nResource table:\n"); 226b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe res.print(false); 227b8dc7bc582ee4acd9d6c1379701a002c5ddbe323Andreas Gampe } 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Asset::ACCESS_BUFFER); 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (manifestAsset == NULL) { 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nNo AndroidManifest.xml found.\n"); 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\nAndroid manifest:\n"); 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree tree; 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(manifestAsset->getBuffer(true), 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski manifestAsset->getLength()); 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete manifestAsset; 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 0; 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 250ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, 2519b8528fee4eed35b8e887ded0851d08eb2b10db6Chih-Hung Hsieh uint32_t attrRes, const String8& attrLabel, String8* outError) 25276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu{ 25376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu Res_value value; 254ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError); 25576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (*outError != "") { 25676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu *outError = "error print resolved resource attribute"; 25776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu return; 25876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 25976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu if (value.dataType == Res_value::TYPE_STRING) { 260ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError); 2612675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s='%s'", attrLabel.string(), 2622675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(result.string()).string()); 26376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else if (Res_value::TYPE_FIRST_INT <= value.dataType && 26476327314d2238e105f8b94909f9c0cf85caca318Maurice Chu value.dataType <= Res_value::TYPE_LAST_INT) { 26576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='%d'", attrLabel.string(), value.data); 26676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } else { 26776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("%s='0x%x'", attrLabel.string(), (int)value.data); 26876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu } 26976327314d2238e105f8b94909f9c0cf85caca318Maurice Chu} 27076327314d2238e105f8b94909f9c0cf85caca318Maurice Chu 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// These are attribute resource constants for the platform, as found 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// in android.R.attr 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskienum { 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LABEL_ATTR = 0x01010001, 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ICON_ATTR = 0x01010002, 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NAME_ATTR = 0x01010003, 277a5018c900f126ee8424c82497f32983873db741bAdam Lesinski PERMISSION_ATTR = 0x01010006, 2789d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski EXPORTED_ATTR = 0x01010010, 2799d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski GRANT_URI_PERMISSIONS_ATTR = 0x0101001b, 28094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski RESOURCE_ATTR = 0x01010025, 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DEBUGGABLE_ATTR = 0x0101000f, 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VALUE_ATTR = 0x01010024, 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_CODE_ATTR = 0x0101021b, 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski VERSION_NAME_ATTR = 0x0101021c, 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_ORIENTATION_ATTR = 0x0101001e, 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MIN_SDK_VERSION_ATTR = 0x0101020c, 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MAX_SDK_VERSION_ATTR = 0x01010271, 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_TOUCH_SCREEN_ATTR = 0x01010227, 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_HARD_KEYBOARD_ATTR = 0x01010229, 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_NAVIGATION_ATTR = 0x0101022a, 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TARGET_SDK_VERSION_ATTR = 0x01010270, 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TEST_ONLY_ATTR = 0x01010272, 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ANY_DENSITY_ATTR = 0x0101026c, 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR = 0x01010281, 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SMALL_SCREEN_ATTR = 0x01010284, 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NORMAL_SCREEN_ATTR = 0x01010285, 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGE_SCREEN_ATTR = 0x01010286, 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski XLARGE_SCREEN_ATTR = 0x010102bf, 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRED_ATTR = 0x0101028e, 302caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski INSTALL_LOCATION_ATTR = 0x010102b7, 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_SIZE_ATTR = 0x010102ca, 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SCREEN_DENSITY_ATTR = 0x010102cb, 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PUBLIC_KEY_ATTR = 0x010103a6, 30994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski CATEGORY_ATTR = 0x010103e8, 3100a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn BANNER_ATTR = 0x10103f2, 311d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn ISGAME_ATTR = 0x10103f4, 312cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn REQUIRED_FEATURE_ATTR = 0x1010557, 313cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn REQUIRED_NOT_FEATURE_ATTR = 0x1010558, 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3162675f769673f69b0661ddee346292f25cb30a296Maurice ChuString8 getComponentName(String8 &pkgName, String8 &componentName) { 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t idx = componentName.find("."); 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 retStr(pkgName); 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx == 0) { 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (idx < 0) { 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += "."; 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retStr += componentName; 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3252675f769673f69b0661ddee346292f25cb30a296Maurice Chu return componentName; 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3272675f769673f69b0661ddee346292f25cb30a296Maurice Chu return retStr; 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3309cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinskistatic void printCompatibleScreens(ResXMLTree& tree, String8* outError) { 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-screens:"); 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 0) { 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 3489cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 3499cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 3509cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 3519cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return; 3529cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 3539cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "screen") { 355ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenSize = AaptXml::getIntegerAttribute(tree, 356ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_SIZE_ATTR); 357ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t screenDensity = AaptXml::getIntegerAttribute(tree, 358ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SCREEN_DENSITY_ATTR); 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize > 0 && screenDensity > 0) { 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!first) { 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(","); 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("'%d/%d'", screenSize, screenDensity); 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 371cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackbornstatic void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1, 372cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn const String8& requiredFeature = String8::empty(), 373cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn const String8& requiredNotFeature = String8::empty()) { 37458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string()); 37558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 37658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 37758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 378cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn if (requiredFeature.length() > 0) { 379cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn printf(" requiredFeature='%s'", requiredFeature.string()); 380cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn } 381cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn if (requiredNotFeature.length() > 0) { 382cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn printf(" requiredNotFeature='%s'", requiredNotFeature.string()); 383cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn } 38458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 38558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 38658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (optional) { 38758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("optional-permission: name='%s'", 38858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski ResTable::normalizeForOutput(name.string()).string()); 38958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski if (maxSdkVersion != -1) { 39058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 39158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 39258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printf("\n"); 39358f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski } 39458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 39558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 3965f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinskistatic void printUsesPermissionSdk23(const String8& name, int maxSdkVersion=-1) { 3975f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf("uses-permission-sdk-23: "); 3985f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 3995f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf("name='%s'", ResTable::normalizeForOutput(name.string()).string()); 4005f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (maxSdkVersion != -1) { 4015f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 4025f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 4035f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf("\n"); 4045f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski} 4055f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 4062386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinskistatic void printUsesImpliedPermission(const String8& name, const String8& reason, 4072386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski const int32_t maxSdkVersion = -1) { 4082386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski printf("uses-implied-permission: name='%s'", 4092386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski ResTable::normalizeForOutput(name.string()).string()); 4102386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski if (maxSdkVersion != -1) { 4112386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski printf(" maxSdkVersion='%d'", maxSdkVersion); 4122386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski } 4132386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski printf(" reason='%s'\n", ResTable::normalizeForOutput(reason.string()).string()); 41458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski} 41558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 4169b8528fee4eed35b8e887ded0851d08eb2b10db6Chih-Hung HsiehVector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost, 41794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 *outError = NULL) 41894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski{ 41994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); 42094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (aidAsset == NULL) { 42194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = "xml resource does not exist"; 42294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 42394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 42494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service"); 42694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 42794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool withinApduService = false; 42894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories; 42994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 43094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski String8 error; 43194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree tree; 43294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength()); 43394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 43494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski size_t len; 43594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski int depth = 0; 43694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski ResXMLTree::event_code_t code; 43794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 43894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (code == ResXMLTree::END_TAG) { 43994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth--; 4409cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4419cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4429cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4439cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4449cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4459cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 44694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 44794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 0 && tag == serviceTagName) { 44894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = false; 44994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 45094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 45194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (code == ResXMLTree::START_TAG) { 45294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski depth++; 4539cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 4549cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 4559cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski *outError = "failed to get XML element name (bad string pool)"; 4569cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski return Vector<String8>(); 4579cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 4589cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 45994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 46094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (depth == 1) { 46194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == serviceTagName) { 46294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinApduService = true; 46394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 46494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 2 && withinApduService) { 46594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "aid-group") { 466ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error); 46794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 46894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (outError != NULL) *outError = error; 46994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return Vector<String8>(); 47094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 47194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 47294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski categories.add(category); 47394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 47494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 47594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 47694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 47794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski aidAsset->close(); 47894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski return categories; 47994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski} 48094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 4819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinskistatic void printComponentPresence(const char* componentName) { 4829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("provides-component:'%s'\n", componentName); 4839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski} 4849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 4852c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 4862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a feature that has been automatically added due to 4872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * a pre-requisite or some other reason. 4882c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct ImpliedFeature { 4905f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ImpliedFeature() : impliedBySdk23(false) {} 4915f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ImpliedFeature(const String8& n, bool sdk23) : name(n), impliedBySdk23(sdk23) {} 4925f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 4932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Name of the implied feature. 4952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 4962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name; 4972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 4982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 4995f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski * Was this implied by a permission from SDK 23 (<uses-permission-sdk-23 />)? 5005f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski */ 5015f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski bool impliedBySdk23; 5025f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 5035f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski /** 5042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * List of human-readable reasons for why this feature was implied. 5052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 5062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski SortedVector<String8> reasons; 5072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 5082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 509694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinskistruct Feature { 510694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski Feature() : required(false), version(-1) {} 511d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh explicit Feature(bool required, int32_t version = -1) : required(required), version(version) {} 512694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 513694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski /** 514694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski * Whether the feature is required. 515694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski */ 516694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski bool required; 517694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 518694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski /** 519694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski * What version of the feature is requested. 520694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski */ 521694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski int32_t version; 522694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski}; 523694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 5242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski/** 5252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Represents a <feature-group> tag in the AndroidManifest.xml 5262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 5272c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistruct FeatureGroup { 528d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup() : openGLESVersion(-1) {} 529d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 5302c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 5312c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Human readable label 5322c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 5332c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 label; 5342c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5352c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski /** 5362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski * Explicit features defined in the group 5372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski */ 538694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski KeyedVector<String8, Feature> features; 539d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 540d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski /** 541d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski * OpenGL ES version required 542d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski */ 543d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski int openGLESVersion; 5442c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski}; 5452c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 546ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinskistatic bool hasFeature(const char* name, const FeatureGroup& grp, 547ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski const KeyedVector<String8, ImpliedFeature>& implied) { 548ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski String8 name8(name); 549ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski ssize_t idx = grp.features.indexOfKey(name8); 550ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski if (idx < 0) { 551ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski idx = implied.indexOfKey(name8); 552ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski } 553ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski return idx >= 0; 554ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski} 555ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski 5562c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addImpliedFeature(KeyedVector<String8, ImpliedFeature>* impliedFeatures, 55743158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski const char* name, const String8& reason, bool sdk23) { 5582c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 name8(name); 5592c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ssize_t idx = impliedFeatures->indexOfKey(name8); 5602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (idx < 0) { 5615f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski idx = impliedFeatures->add(name8, ImpliedFeature(name8, sdk23)); 5622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5635f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 5645f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ImpliedFeature* feature = &impliedFeatures->editValueAt(idx); 5655f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 5665f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski // A non-sdk 23 implied feature takes precedence. 5675f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (feature->impliedBySdk23 && !sdk23) { 5685f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski feature->impliedBySdk23 = false; 5695f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 57043158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski feature->reasons.add(reason); 5712c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 5722c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5735f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinskistatic void printFeatureGroupImpl(const FeatureGroup& grp, 5745f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski const KeyedVector<String8, ImpliedFeature>* impliedFeatures) { 5752c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("feature-group: label='%s'\n", grp.label.string()); 5762c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 577d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (grp.openGLESVersion > 0) { 578d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski printf(" uses-gl-es: '0x%x'\n", grp.openGLESVersion); 579d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 580d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 5812c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatures = grp.features.size(); 5822c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatures; i++) { 583694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski const Feature& feature = grp.features[i]; 584694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski const bool required = feature.required; 585694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski const int32_t version = feature.version; 5862c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const String8& featureName = grp.features.keyAt(i); 588694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski printf(" uses-feature%s: name='%s'", (required ? "" : "-not-required"), 5892c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski ResTable::normalizeForOutput(featureName.string()).string()); 590694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 591694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski if (version > 0) { 592694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski printf(" version='%d'", version); 593694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski } 594694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski printf("\n"); 5952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 5962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 5972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numImpliedFeatures = 5982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski (impliedFeatures != NULL) ? impliedFeatures->size() : 0; 5992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numImpliedFeatures; i++) { 6002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const ImpliedFeature& impliedFeature = impliedFeatures->valueAt(i); 6012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(impliedFeature.name) >= 0) { 6022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // The feature is explicitly set, no need to use implied 6032c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // definition. 6042c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski continue; 6052c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6062c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski String8 printableFeatureName(ResTable::normalizeForOutput( 6082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski impliedFeature.name.string())); 6095f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski const char* sdk23Suffix = impliedFeature.impliedBySdk23 ? "-sdk-23" : ""; 6105f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 6115f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf(" uses-feature%s: name='%s'\n", sdk23Suffix, printableFeatureName.string()); 6125f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf(" uses-implied-feature%s: name='%s' reason='", sdk23Suffix, 6135f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printableFeatureName.string()); 6142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numReasons = impliedFeature.reasons.size(); 6152c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numReasons; j++) { 6162c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("%s", impliedFeature.reasons[j].string()); 6172c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (j + 2 < numReasons) { 6182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", "); 6192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (j + 1 < numReasons) { 6202c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf(", and "); 6212c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6222c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printf("'\n"); 6242c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6252c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 6262c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6275f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinskistatic void printFeatureGroup(const FeatureGroup& grp) { 6285f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printFeatureGroupImpl(grp, NULL); 6295f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski} 6305f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 6315f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinskistatic void printDefaultFeatureGroup(const FeatureGroup& grp, 6325f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski const KeyedVector<String8, ImpliedFeature>& impliedFeatures) { 6335f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printFeatureGroupImpl(grp, &impliedFeatures); 6345f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski} 6355f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 6362c72b6822debb08fe997926eedc110f62d287d34Adam Lesinskistatic void addParentFeatures(FeatureGroup* grp, const String8& name) { 6372c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (name == "android.hardware.camera.autofocus" || 6382c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.camera.flash") { 639694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski grp->features.add(String8("android.hardware.camera"), Feature(true)); 6402c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.location.gps" || 6412c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski name == "android.hardware.location.network") { 642694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski grp->features.add(String8("android.hardware.location"), Feature(true)); 643ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski } else if (name == "android.hardware.faketouch.multitouch") { 644ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski grp->features.add(String8("android.hardware.faketouch"), Feature(true)); 645ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski } else if (name == "android.hardware.faketouch.multitouch.distinct" || 646ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski name == "android.hardware.faketouch.multitouch.jazzhands") { 647ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski grp->features.add(String8("android.hardware.faketouch.multitouch"), Feature(true)); 648ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski grp->features.add(String8("android.hardware.faketouch"), Feature(true)); 6492c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (name == "android.hardware.touchscreen.multitouch") { 650694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), Feature(true)); 651ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski } else if (name == "android.hardware.touchscreen.multitouch.distinct" || 652ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski name == "android.hardware.touchscreen.multitouch.jazzhands") { 653694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski grp->features.add(String8("android.hardware.touchscreen.multitouch"), Feature(true)); 654694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski grp->features.add(String8("android.hardware.touchscreen"), Feature(true)); 655d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else if (name == "android.hardware.opengles.aep") { 656d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski const int openGLESVersion31 = 0x00030001; 657d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (openGLESVersion31 > grp->openGLESVersion) { 658d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp->openGLESVersion = openGLESVersion31; 659d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 6602c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 6612c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski} 6622c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 6635f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinskistatic void addImpliedFeaturesForPermission(const int targetSdk, const String8& name, 6645f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski KeyedVector<String8, ImpliedFeature>* impliedFeatures, 6655f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski bool impliedBySdk23Permission) { 6665f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "android.permission.CAMERA") { 6675f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.camera", 66843158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 66943158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 6705f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.ACCESS_FINE_LOCATION") { 67143158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski if (targetSdk < SDK_LOLLIPOP) { 67243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location.gps", 67343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 67443158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 67543158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location.gps", 67643158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("targetSdkVersion < %d", SDK_LOLLIPOP), 67743158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 67843158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski } 6795f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location", 68043158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 68143158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 6825f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { 68343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski if (targetSdk < SDK_LOLLIPOP) { 68443158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location.network", 68543158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 68643158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 68743158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location.network", 68843158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("targetSdkVersion < %d", SDK_LOLLIPOP), 68943158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 69043158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski } 6915f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location", 69243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 69343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 69443158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski } else if (name == "android.permission.ACCESS_MOCK_LOCATION" || 69543158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || 6965f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.INSTALL_LOCATION_PROVIDER") { 6975f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.location", 69843158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 69943158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 7005f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.BLUETOOTH" || 7015f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.BLUETOOTH_ADMIN") { 70243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski if (targetSdk > SDK_DONUT) { 7035f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.bluetooth", 70443158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 70543158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 7065f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.bluetooth", 70743158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("targetSdkVersion > %d", SDK_DONUT), 70843158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 7095f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 7105f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.RECORD_AUDIO") { 7115f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.microphone", 71243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 71343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 7145f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.ACCESS_WIFI_STATE" || 7155f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.CHANGE_WIFI_STATE" || 7165f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { 7175f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.wifi", 71843158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8::format("requested %s permission", name.string()), 71943158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 7205f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.CALL_PHONE" || 7215f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.CALL_PRIVILEGED" || 7225f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.MODIFY_PHONE_STATE" || 7235f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.PROCESS_OUTGOING_CALLS" || 7245f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.READ_SMS" || 7255f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.RECEIVE_SMS" || 7265f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.RECEIVE_MMS" || 7275f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.RECEIVE_WAP_PUSH" || 7285f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.SEND_SMS" || 7295f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.WRITE_APN_SETTINGS" || 7305f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name == "android.permission.WRITE_SMS") { 7315f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeature(impliedFeatures, "android.hardware.telephony", 73243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8("requested a telephony permission"), 73343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski impliedBySdk23Permission); 7345f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 7355f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski} 7365f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "dump" command, to extract select data from an archive. 739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiextern char CONSOLE_DATA[2925]; // see EOF 741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doDump(Bundle* bundle) 742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump option specified\n"); 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump file specified\n"); 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* option = bundle->getFileSpecEntry(0); 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = bundle->getFileSpecEntry(1); 757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetManager assets; 759f85e41f29a0e9313c2d4725f9d9648591ea49f3bNarayan Kamath int32_t assetsCookie; 760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 1; 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make a dummy config for retrieving resources... we need to supply 766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // non-default values for some configs so that we can retrieve resources 767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the app that don't have a default. The most important of these is 768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the API version because key resources like icons will have an implicit 769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // version if they are using newer config types like density. 770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config config; 77191447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath memset(&config, 0, sizeof(ResTable_config)); 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[0] = 'e'; 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.language[1] = 'n'; 774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[0] = 'U'; 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.country[1] = 'S'; 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = ResTable_config::ORIENTATION_PORT; 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.density = ResTable_config::DENSITY_MEDIUM; 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.sdkVersion = 10000; // Very high. 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = 320; 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = 480; 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = 320; 782c2dea8daea2ae0001d56689d96ce1066012b7b40Adam Lesinski config.screenLayout |= ResTable_config::SCREENSIZE_NORMAL; 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable& res = assets.getResources(false); 7866800165351b693fa7e4bcf0f205655f0cd16b361Dan Albert if (res.getError() != NO_ERROR) { 78725e9d55e964c180ec6e57ba1d977d6c2e1115f5aAdam Lesinski fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n"); 78863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski return 1; 78963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski } 79063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 791694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski // Source for AndroidManifest.xml 79210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski const String8 manifestFile("AndroidManifest.xml"); 793694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 7942cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // The dynamicRefTable can be null if there are no resources for this asset cookie. 7952cb761e3ddb9d68ab430013e9cd15ecaab9fbc62Adam Lesinski // This fine. 79663e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie); 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 79863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski Asset* asset = NULL; 79963e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("resources", option) == 0) { 801ba3fe56edc1da4dad0d831a1892e7b1c3c20c437Elliott Hughes#ifndef __ANDROID__ 802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.print(bundle->getValues()); 803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("strings", option) == 0) { 806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResStringPool* pool = res.getTableStringBlock(0); 807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(pool); 808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmltree", option) == 0) { 810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 81763e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 81863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 820fcb5f7bf36cb77a359fd3fb01af7bf0140da16beAdam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s not found\n", resname); 821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printXMLBlock(&tree); 831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.uninit(); 832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("xmlstrings", option) == 0) { 837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 3) { 838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i=2; i<bundle->getFileSpecCount(); i++) { 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* resname = bundle->getFileSpecEntry(i); 84463e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER); 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 85063e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printStringPool(&tree.getStrings()); 857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset = NULL; 859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 86263e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER); 863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset == NULL) { 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86863e646eed5a8d7f5d04544ac8628f65b0173cf3aAdam Lesinski ResXMLTree tree(dynamicRefTable); 869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tree.setTo(asset->getBuffer(true), 870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski asset->getLength()) != NO_ERROR) { 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.restart(); 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp("permissions", option) == 0) { 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 8805f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && 8815f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski code != ResXMLTree::BAD_DOCUMENT) { 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 8909cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 8919cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 89210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 89310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: failed to get XML element name (bad string pool)"); 8949cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 8959cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 8969cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d tag %s\n", depth, tag.string()); 898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 90010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 90110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: manifest does not start with <manifest> tag"); 902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 904ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 9052675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); 9065f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (depth == 2) { 9075f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (tag == "permission") { 9085f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 error; 9095f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 9105f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (error != "") { 91110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 91210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name': %s", error.string()); 9135f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 9145f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 9155f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 9165f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "") { 91710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 91810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: missing 'android:name' for permission"); 9195f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 9205f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 9215f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf("permission: %s\n", 9225f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(name.string()).string()); 9235f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (tag == "uses-permission") { 9245f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 error; 9255f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 9265f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (error != "") { 92710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 92810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 9295f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 9305f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 9315f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 9325f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "") { 93310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 93410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: missing 'android:name' for uses-permission"); 9355f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 9365f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 9375f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printUsesPermission(name, 9385f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 9395f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 9405f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") { 9415f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 error; 9425f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 9435f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (error != "") { 94410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 94510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 9465f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 9475f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 9485f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 9495f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "") { 95010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 95110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: missing 'android:name' for uses-permission-sdk-23"); 9525f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 9535f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 9545f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printUsesPermissionSdk23( 9555f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name, 9565f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badging", option) == 0) { 961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8> locales; 962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getLocales(&locales); 963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SortedVector<int> densities; 967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = configs.size(); 968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NC; i++) { 969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int dens = configs[i].density; 970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dens == 0) { 971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dens = 160; 972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski densities.add(dens); 974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int depth = 0; 979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 error; 980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinActivity = false; 981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isMainActivity = false; 982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isLauncherActivity = false; 9830a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn bool isLeanbackLauncherActivity = false; 984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isSearchable = false; 985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinApplication = false; 986ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright bool withinSupportsInput = false; 9872c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski bool withinFeatureGroup = false; 988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinReceiver = false; 989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinService = false; 9909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool withinProvider = false; 991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool withinIntentFilter = false; 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasMainActivity = false; 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherActivities = false; 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherReceivers = false; 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasOtherServices = false; 9969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasIntentFilter = false; 9979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWallpaperService = false; 999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasImeService = false; 1000a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasAccessibilityService = false; 1001a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasPrintService = false; 1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWidgetReceivers = false; 1003a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasDeviceAdminReceiver = false; 100494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasPaymentService = false; 10059d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasDocumentsProvider = false; 10069d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraActivity = false; 10079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasCameraSecureActivity = false; 10089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasLauncher = false; 10099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasNotificationListenerService = false; 1010eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasDreamService = false; 10119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actMainActivity = false; 1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWidgetReceivers = false; 1014a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actDeviceAdminEnabled = false; 1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actImeService = false; 1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool actWallpaperService = false; 1017a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actAccessibilityService = false; 1018a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool actPrintService = false; 101994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actHostApduService = false; 102094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool actOffHostApduService = false; 10219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actDocumentsProvider = false; 10229d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actNotificationListenerService = false; 1023eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool actDreamService = false; 10249d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCamera = false; 10259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool actCameraSecure = false; 10269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool catLauncher = false; 102794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaHostPaymentCategory = false; 102894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasMetaOffHostPaymentCategory = false; 1029a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1030a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // These permissions are required by services implementing services 1031a5018c900f126ee8424c82497f32983873db741bAdam Lesinski // the system binds to (IME, Accessibility, PrintServices, etc.) 1032a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindDeviceAdminPermission = false; 1033a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindInputMethodPermission = false; 1034a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindAccessibilityServicePermission = false; 1035a5018c900f126ee8424c82497f32983873db741bAdam Lesinski bool hasBindPrintServicePermission = false; 103694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool hasBindNfcServicePermission = false; 10379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasRequiredSafAttributes = false; 10389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski bool hasBindNotificationListenerServicePermission = false; 1039eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock bool hasBindDreamServicePermission = false; 1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // These two implement the implicit permissions that are granted 1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to pre-1.6 applications. 1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteExternalStoragePermission = false; 10442386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski int32_t writeExternalStoragePermissionMaxSdkVersion = -1; 1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadPhoneStatePermission = false; 1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If an app requests write storage, they will also get read storage. 1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadExternalStoragePermission = false; 1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Implement transition to read and write call log. 1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadContactsPermission = false; 1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteContactsPermission = false; 1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasReadCallLogPermission = false; 1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasWriteCallLogPermission = false; 1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1056e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If an app declares itself as multiArch, we report the 1057e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // native libraries differently. 1058e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool hasMultiArch = false; 1059e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This next group of variables is used to implement a group of 1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // backward-compatibility heuristics necessitated by the addition of 1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // some new uses-feature constants in 2.1 and 2.2. In most cases, the 1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // heuristic is "if an app requests a permission but doesn't explicitly 1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // request the corresponding <uses-feature>, presume it's there anyway". 10652c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 2.2 also added some other features that apps can request, but that 1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // have no corresponding permission, so we cannot implement any 1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // back-compatibility heuristic for them. The below are thus unnecessary 1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (but are retained here for documentary purposes.) 1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specCompassFeature = false; 1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAccelerometerFeature = false; 1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specProximityFeature = false; 1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specAmbientLightFeature = false; 1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //bool specLiveWallpaperFeature = false; 1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int targetSdk = 0; 1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int smallScreen = 1; 1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int normalScreen = 1; 1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largeScreen = 1; 1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int xlargeScreen = 1; 1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int anyDensity = 1; 1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int requiresSmallestWidthDp = 0; 1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatibleWidthLimitDp = 0; 1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int largestWidthLimitDp = 0; 1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 pkg; 1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityName; 1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityLabel; 1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 activityIcon; 10890a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn String8 activityBanner; 1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 receiverName; 1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 serviceName; 1092ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright Vector<String8> supportedInput; 10932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 10942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup commonFeatures; 10952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski Vector<FeatureGroup> featureGroups; 10962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski KeyedVector<String8, ImpliedFeature> impliedFeatures; 10972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 10985f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && 10995f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski code != ResXMLTree::BAD_DOCUMENT) { 1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth < 2) { 1103ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinSupportsInput && !supportedInput.isEmpty()) { 1104ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("supports-input: '"); 1105ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright const size_t N = supportedInput.size(); 1106ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright for (size_t i=0; i<N; i++) { 11072675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("%s", ResTable::normalizeForOutput( 11082675f769673f69b0661ddee346292f25cb30a296Maurice Chu supportedInput[i].string()).string()); 1109ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (i != N - 1) { 1110ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("' '"); 1111ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 1112ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("'\n"); 1113ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1114ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1115ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.clear(); 1116ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1118ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = false; 11192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = false; 1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 3) { 11210a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (withinActivity && isMainActivity) { 11222675f769673f69b0661ddee346292f25cb30a296Maurice Chu String8 aName(getComponentName(pkg, activityName)); 11230a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLauncherActivity) { 11240a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("launchable-activity:"); 11259eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 11269eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 11279eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 11280a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 11290a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s'\n", 11305f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(activityLabel.string()) 11315f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski .string(), 11325f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(activityIcon.string()) 11335f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski .string()); 11340a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 11350a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (isLeanbackLauncherActivity) { 11360a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf("leanback-launchable-activity:"); 11379eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn if (aName.length() > 0) { 11389eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn printf(" name='%s' ", 11399eaaaf0fe3917f4fec85d3e45da37914654847ecTim Kilbourn ResTable::normalizeForOutput(aName.string()).string()); 11400a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 11410a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn printf(" label='%s' icon='%s' banner='%s'\n", 11425f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(activityLabel.string()) 11435f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski .string(), 11445f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(activityIcon.string()) 11455f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski .string(), 11465f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(activityBanner.string()) 11475f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski .string()); 1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasIntentFilter) { 1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherActivities |= withinActivity; 1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherReceivers |= withinReceiver; 1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasOtherServices |= withinService; 115494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 115594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (withinService) { 115694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory && 115794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 115894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory && 115994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission); 116094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 11659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 11670a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false; 1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth < 4) { 1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinIntentFilter) { 1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (withinActivity) { 1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasMainActivity |= actMainActivity; 11729d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasLauncher |= catLauncher; 11739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraActivity |= actCamera; 11749d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasCameraSecureActivity |= actCameraSecure; 11755f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasOtherActivities |= 11765f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski !actMainActivity && !actCamera && !actCameraSecure; 1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinReceiver) { 1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWidgetReceivers |= actWidgetReceivers; 1179a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasDeviceAdminReceiver |= (actDeviceAdminEnabled && 1180a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission); 11815f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasOtherReceivers |= 11825f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski (!actWidgetReceivers && !actDeviceAdminEnabled); 1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (withinService) { 1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasImeService |= actImeService; 1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWallpaperService |= actWallpaperService; 1186a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasAccessibilityService |= (actAccessibilityService && 1187a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission); 11885f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasPrintService |= 11895f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski (actPrintService && hasBindPrintServicePermission); 11909d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasNotificationListenerService |= actNotificationListenerService && 11919d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission; 1192eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasDreamService |= actDreamService && hasBindDreamServicePermission; 1193a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasOtherServices |= (!actImeService && !actWallpaperService && 119494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski !actAccessibilityService && !actPrintService && 11959d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actHostApduService && !actOffHostApduService && 11969d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski !actNotificationListenerService); 11979d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 11985f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasDocumentsProvider |= 11995f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski actDocumentsProvider && hasRequiredSafAttributes; 1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinIntentFilter = false; 1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth++; 12109cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski 12119cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski const char16_t* ctag16 = tree.getElementName(&len); 12129cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (ctag16 == NULL) { 121310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 121410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: failed to get XML element name (bad string pool)"); 12159cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 12169cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 12179cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski String8 tag(ctag16); 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Depth %d, %s\n", depth, tag.string()); 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (depth == 1) { 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag != "manifest") { 122110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 122210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: manifest does not start with <manifest> tag"); 1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1225ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); 12262675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("package: name='%s' ", 12272675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(pkg.string()).string()); 1228ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR, 1229ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 123110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 123210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:versionCode' attribute: %s", 1233ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (versionCode > 0) { 1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='%d' ", versionCode); 1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("versionCode='' "); 1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1241ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 versionName = AaptXml::getResolvedAttribute(res, tree, 1242ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski VERSION_NAME_ATTR, &error); 1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 124410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 124510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:versionName' attribute: %s", 1246ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 124925d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("versionName='%s'", 12502675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(versionName.string()).string()); 125125d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski 1252ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 splitName = AaptXml::getAttribute(tree, NULL, "split"); 125325d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski if (!splitName.isEmpty()) { 125425d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf(" split='%s'", ResTable::normalizeForOutput( 125525d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski splitName.string()).string()); 125625d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski } 1257ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 12585283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski String8 platformVersionName = AaptXml::getAttribute(tree, NULL, 12595283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski "platformBuildVersionName"); 12605283faba4a75a4d1fd9990637d22768e423895e3Adam Lesinski printf(" platformBuildVersionName='%s'", platformVersionName.string()); 126125d35a9d68fed6304352d0bfc2e0d581ed47f8b5Adam Lesinski printf("\n"); 1262caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1263ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree, 1264ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski INSTALL_LOCATION_ATTR, &error); 1265caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (error != "") { 126610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 126710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:installLocation' attribute: %s", 1268caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski error.string()); 1269caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1270caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1271caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski 1272caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski if (installLocation >= 0) { 1273caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("install-location:'"); 1274caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski switch (installLocation) { 1275caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 0: 1276caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("auto"); 1277caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1278caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 1: 1279caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("internalOnly"); 1280caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1281caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski case 2: 1282caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("preferExternal"); 1283caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski break; 1284caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski default: 1285caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski fprintf(stderr, "Invalid installLocation %d\n", installLocation); 1286caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski goto bail; 1287caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1288caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski printf("'\n"); 1289caf797c84a6a2829662872e0df93fcd61da78d51Adam Lesinski } 1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (depth == 2) { 1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = false; 1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tag == "application") { 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinApplication = true; 1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 label; 1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 1299a77685fa59a327b33e7acbcefe35e63243014cbdAdam Lesinski assets.setConfiguration(config, localeStr != NULL ? localeStr : ""); 1300ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, 1301ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (llabel != "") { 1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 13052675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-label:'%s'\n", 13062675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (label == "") { 1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label = llabel; 1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-label-%s:'%s'\n", localeStr, 13122675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(llabel.string()).string()); 1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config tmpConfig = config; 1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tmpConfig.density = densities[i]; 1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(tmpConfig); 1322ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, 1323ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (icon != "") { 13252675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application-icon-%d:'%s'\n", densities[i], 13262675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(icon.string()).string()); 1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets.setConfiguration(config); 1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1331ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error); 1332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 133310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 133410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:icon' attribute: %s", error.string()); 1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1337ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0, 1338ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 134010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 134110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:testOnly' attribute: %s", 1342ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1345d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn 13465f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 banner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, 13475f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski &error); 1348d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn if (error != "") { 134910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 135010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:banner' attribute: %s", error.string()); 1351d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn goto bail; 1352d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn } 13532675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("application: label='%s' ", 13542675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(label.string()).string()); 1355d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn printf("icon='%s'", ResTable::normalizeForOutput(icon.string()).string()); 1356d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn if (banner != "") { 13575f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printf(" banner='%s'", 13585f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski ResTable::normalizeForOutput(banner.string()).string()); 1359d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn } 1360d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn printf("\n"); 1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (testOnly != 0) { 1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("testOnly='%d'\n", testOnly); 1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1365d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn int32_t isGame = AaptXml::getResolvedIntegerAttribute(res, tree, 1366d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn ISGAME_ATTR, 0, &error); 1367d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn if (error != "") { 136810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 136910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:isGame' attribute: %s", error.string()); 1370d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn goto bail; 1371d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn } 1372d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn if (isGame != 0) { 1373d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn printf("application-isGame\n"); 1374d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn } 1375d9b1cad71e8aaf94e7738d2e47d3a06daa3cdf2dTim Kilbourn 1376ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree, 1377ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski DEBUGGABLE_ATTR, 0, &error); 1378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 137910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 138010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:debuggable' attribute: %s", 1381ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski error.string()); 1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (debuggable != 0) { 1385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("application-debuggable\n"); 1386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1387e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 1388e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // We must search by name because the multiArch flag hasn't been API 1389e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // frozen yet. 1390e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski int32_t multiArchIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, 1391e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski "multiArch"); 1392e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (multiArchIndex >= 0) { 1393e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski Res_value value; 1394e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (tree.getAttributeValue(multiArchIndex, &value) != NO_ERROR) { 1395e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (value.dataType >= Res_value::TYPE_FIRST_INT && 1396e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski value.dataType <= Res_value::TYPE_LAST_INT) { 1397e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski hasMultiArch = value.data; 1398e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1399e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1400e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-sdk") { 14025f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, 14035f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski &error); 1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1406ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, 1407ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski MIN_SDK_VERSION_ATTR, &error); 1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 140910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 141010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:minSdkVersion' attribute: %s", 1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut") targetSdk = 4; 14152675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("sdkVersion:'%s'\n", 14162675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("sdkVersion:'%d'\n", code); 1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1421ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR); 1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != -1) { 1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("maxSdkVersion:'%d'\n", code); 1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1425ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error = ""; 1428ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, 1429ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski TARGET_SDK_VERSION_ATTR, &error); 1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 143110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 143210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:targetSdkVersion' attribute: %s", 1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski error.string()); 1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == "Donut" && targetSdk < 4) targetSdk = 4; 14372675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("targetSdkVersion:'%s'\n", 14382675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code != -1) { 1440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < code) { 1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski targetSdk = code; 1442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("targetSdkVersion:'%d'\n", code); 1444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-configuration") { 1446ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree, 1447ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_TOUCH_SCREEN_ATTR, 0); 1448ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree, 1449ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_KEYBOARD_TYPE_ATTR, 0); 1450ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree, 1451ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_HARD_KEYBOARD_ATTR, 0); 1452ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqNavigation = AaptXml::getIntegerAttribute(tree, 1453ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_NAVIGATION_ATTR, 0); 1454ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree, 1455ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQ_FIVE_WAY_NAV_ATTR, 0); 1456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("uses-configuration:"); 1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqTouchScreen != 0) { 1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqTouchScreen='%d'", reqTouchScreen); 1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqKeyboardType != 0) { 1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqKeyboardType='%d'", reqKeyboardType); 1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqHardKeyboard != 0) { 1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqHardKeyboard='%d'", reqHardKeyboard); 1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqNavigation != 0) { 1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqNavigation='%d'", reqNavigation); 1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (reqFiveWayNav != 0) { 1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" reqFiveWayNav='%d'", reqFiveWayNav); 1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 1473ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "supports-input") { 1474ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinSupportsInput = true; 1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-screens") { 1476ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski smallScreen = AaptXml::getIntegerAttribute(tree, 1477ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski SMALL_SCREEN_ATTR, 1); 1478ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski normalScreen = AaptXml::getIntegerAttribute(tree, 1479ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski NORMAL_SCREEN_ATTR, 1); 1480ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski largeScreen = AaptXml::getIntegerAttribute(tree, 1481ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski LARGE_SCREEN_ATTR, 1); 1482ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski xlargeScreen = AaptXml::getIntegerAttribute(tree, 1483ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski XLARGE_SCREEN_ATTR, 1); 1484ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski anyDensity = AaptXml::getIntegerAttribute(tree, 1485ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ANY_DENSITY_ATTR, 1); 1486ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree, 1487ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0); 1488ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree, 1489ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0); 1490ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski largestWidthLimitDp = AaptXml::getIntegerAttribute(tree, 1491ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski LARGEST_WIDTH_LIMIT_DP_ATTR, 0); 14922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (tag == "feature-group") { 14932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski withinFeatureGroup = true; 14942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup group; 1495ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error); 14962c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (error != "") { 149710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 149810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:label' attribute: %s", error.string()); 14992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski goto bail; 15002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 15012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski featureGroups.add(group); 15022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-feature") { 1504ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 1506694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski const char* androidSchema = 1507694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski "http://schemas.android.com/apk/res/android"; 1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1509694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski int32_t req = AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1, 1510694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski &error); 1511694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski if (error != "") { 1512694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 1513694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski "failed to read attribute 'android:required': %s", 1514694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski error.string()); 1515694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski goto bail; 1516694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski } 1517694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 1518694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski int32_t version = AaptXml::getIntegerAttribute(tree, androidSchema, 1519694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski "version", 0, &error); 1520694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski if (error != "") { 1521694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 1522694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski "failed to read attribute 'android:version': %s", 1523694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski error.string()); 1524694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski goto bail; 1525694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski } 1526694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 1527694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski commonFeatures.features.add(name, Feature(req != 0, version)); 15282c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (req) { 15292c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski addParentFeatures(&commonFeatures, name); 1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1532ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int vers = AaptXml::getIntegerAttribute(tree, 1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski GL_ES_VERSION_ATTR, &error); 1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error == "") { 1535d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > commonFeatures.openGLESVersion) { 1536d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.openGLESVersion = vers; 1537d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-permission") { 1541ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 15425f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (error != "") { 154310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 154410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 15455f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 15465f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 154758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski 15485f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "") { 154910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 155010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: missing 'android:name' for uses-permission"); 15515f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 15525f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 15535f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 15545f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeaturesForPermission(targetSdk, name, &impliedFeatures, false); 15555f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 15562386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski const int32_t maxSdkVersion = 15572386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, -1); 1558cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn const String8 requiredFeature = AaptXml::getAttribute(tree, 1559cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn REQUIRED_FEATURE_ATTR, &error); 1560cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn const String8 requiredNotFeature = AaptXml::getAttribute(tree, 1561cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn REQUIRED_NOT_FEATURE_ATTR, &error); 15622386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski 15635f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { 15645f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasWriteExternalStoragePermission = true; 15652386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski writeExternalStoragePermissionMaxSdkVersion = maxSdkVersion; 15665f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { 15675f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasReadExternalStoragePermission = true; 15685f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.READ_PHONE_STATE") { 15695f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasReadPhoneStatePermission = true; 15705f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.READ_CONTACTS") { 15715f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasReadContactsPermission = true; 15725f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.WRITE_CONTACTS") { 15735f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasWriteContactsPermission = true; 15745f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.READ_CALL_LOG") { 15755f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasReadCallLogPermission = true; 15765f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (name == "android.permission.WRITE_CALL_LOG") { 15775f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski hasWriteCallLogPermission = true; 15785f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 15795f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 15805f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printUsesPermission(name, 15815f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, 1582cd154e95353e7af11314d2339500d6c7f85e181aDianne Hackborn maxSdkVersion, requiredFeature, requiredNotFeature); 15835f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 15845f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") { 15855f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 15865f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (error != "") { 158710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 158810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 15915f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 15925f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski if (name == "") { 159310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 159410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR: missing 'android:name' for uses-permission-sdk-23"); 15955f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski goto bail; 15965f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } 15975f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 15985f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski addImpliedFeaturesForPermission(targetSdk, name, &impliedFeatures, true); 15995f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 16005f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printUsesPermissionSdk23( 16015f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski name, AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); 16025f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski 1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "uses-package") { 1604ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 16062675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("uses-package:'%s'\n", 16072675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 160910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 161010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 161110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski goto bail; 1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "original-package") { 1614ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 16162675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("original-package:'%s'\n", 16172675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 161910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 162010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 162110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski goto bail; 1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "supports-gl-texture") { 1624ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 16262675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("supports-gl-texture:'%s'\n", 16272675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string()); 1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 162910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 163010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 163110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski goto bail; 1632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "compatible-screens") { 16349cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski printCompatibleScreens(tree, &error); 16359cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski if (error != "") { 163610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 163710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting compatible screens: %s", error.string()); 16389cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski goto bail; 16399cb2c68fafce55d43aacb2202deb882b986fa237Adam Lesinski } 1640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski depth--; 1641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (tag == "package-verifier") { 1642ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name != "" && error == "") { 16445f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, 16455f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski &error); 1646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (publicKey != "" && error == "") { 1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("package-verifier: name='%s' publicKey='%s'\n", 16482675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(name.string()).string(), 16492675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(publicKey.string()).string()); 1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1653ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (depth == 3) { 1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinActivity = false; 1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinReceiver = false; 1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski withinService = false; 16579d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = false; 1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasIntentFilter = false; 165994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory = false; 166094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory = false; 166194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindDeviceAdminPermission = false; 166294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindInputMethodPermission = false; 166394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindAccessibilityServicePermission = false; 166494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindPrintServicePermission = false; 166594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = false; 16669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes = false; 16679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = false; 1668eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = false; 1669ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (withinApplication) { 1670ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if(tag == "activity") { 1671ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinActivity = true; 1672ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1673ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 167410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 167510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", 1676ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1677ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1678ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1680ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, 1681ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1682ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 168310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 168410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:label' attribute: %s", 1685ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1686ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1687ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1689ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, 1690ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1691ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 169210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 169310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:icon' attribute: %s", 1694ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1695ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1696ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1698ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, 1699ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 17000a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn if (error != "") { 170110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 170210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:banner' attribute: %s", 17030a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn error.string()); 17040a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn goto bail; 17050a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } 17060a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn 1707ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree, 1708ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright SCREEN_ORIENTATION_ATTR, &error); 1709ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error == "") { 1710ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (orien == 0 || orien == 6 || orien == 8) { 1711ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests landscape, sensorLandscape, or reverseLandscape. 171243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski addImpliedFeature( 171343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski &impliedFeatures, "android.hardware.screen.landscape", 171443158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8("one or more activities have specified a " 171543158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski "landscape orientation"), 171643158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski false); 1717ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (orien == 1 || orien == 7 || orien == 9) { 1718ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright // Requests portrait, sensorPortrait, or reversePortrait. 171943158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski addImpliedFeature( 172043158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski &impliedFeatures, "android.hardware.screen.portrait", 172143158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8("one or more activities have specified a " 172243158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski "portrait orientation"), 172343158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski false); 1724ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1726ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "uses-library") { 1727ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1728ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 172910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 1730ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for uses-library" 173110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski " %s", error.string()); 1732ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1733ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1734ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int req = AaptXml::getIntegerAttribute(tree, 1735ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski REQUIRED_ATTR, 1); 1736ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright printf("uses-library%s:'%s'\n", 17372675f769673f69b0661ddee346292f25cb30a296Maurice Chu req ? "" : "-not-required", ResTable::normalizeForOutput( 17382675f769673f69b0661ddee346292f25cb30a296Maurice Chu libraryName.string()).string()); 1739ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "receiver") { 1740ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinReceiver = true; 1741ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1743ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 174410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 1745ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright "ERROR getting 'android:name' attribute for receiver:" 174610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski " %s", error.string()); 1747ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1748ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1749a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1750ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR, 1751ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1752a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1753a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_DEVICE_ADMIN") { 1754a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindDeviceAdminPermission = true; 1755a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1756a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 175710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 17585f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "ERROR getting 'android:permission' attribute for" 175910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski " receiver '%s': %s", 17605f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski receiverName.string(), error.string()); 1761a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1762ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (tag == "service") { 1763ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright withinService = true; 1764ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1766ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 176710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 176810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute for " 176910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "service:%s", error.string()); 1770ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1771ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1772a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1773ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR, 1774ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1775a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error == "") { 1776a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (permission == "android.permission.BIND_INPUT_METHOD") { 1777a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindInputMethodPermission = true; 17785f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (permission == 17795f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.permission.BIND_ACCESSIBILITY_SERVICE") { 1780a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindAccessibilityServicePermission = true; 17815f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (permission == 17825f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.permission.BIND_PRINT_SERVICE") { 1783a5018c900f126ee8424c82497f32983873db741bAdam Lesinski hasBindPrintServicePermission = true; 17845f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (permission == 17855f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.permission.BIND_NFC_SERVICE") { 178694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasBindNfcServicePermission = true; 17875f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (permission == 17885f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { 17899d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasBindNotificationListenerServicePermission = true; 1790eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (permission == "android.permission.BIND_DREAM_SERVICE") { 1791eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock hasBindDreamServicePermission = true; 1792a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1793a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else { 179410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 179510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:permission' attribute for " 179610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "service '%s': %s", serviceName.string(), error.string()); 1797a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 17989d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (tag == "provider") { 17999d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski withinProvider = true; 18009d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1801ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski bool exported = AaptXml::getResolvedIntegerAttribute(res, tree, 1802ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski EXPORTED_ATTR, &error); 18039d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 180410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 18055f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "ERROR getting 'android:exported' attribute for provider:" 180610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski " %s", error.string()); 18079d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 18089d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18099d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1810ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute( 1811ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski res, tree, GRANT_URI_PERMISSIONS_ATTR, &error); 18129d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 181310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 18145f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "ERROR getting 'android:grantUriPermissions' attribute for " 181510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "provider: %s", error.string()); 18169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 18179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1819ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 permission = AaptXml::getResolvedAttribute(res, tree, 1820ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski PERMISSION_ATTR, &error); 18219d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (error != "") { 182210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 182310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:permission' attribute for " 182410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "provider: %s", error.string()); 18259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski goto bail; 18269d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 18279d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 18289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski hasRequiredSafAttributes |= exported && grantUriPermissions && 18299d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski permission == "android.permission.MANAGE_DOCUMENTS"; 18309d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 1831ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (bundle->getIncludeMetaData() && tag == "meta-data") { 1832ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 metaDataName = AaptXml::getResolvedAttribute(res, tree, 1833ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski NAME_ATTR, &error); 1834ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 183510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 183610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute for " 183710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "meta-data: %s", error.string()); 1838ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1839ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 18402675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf("meta-data: name='%s' ", 18412675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(metaDataName.string()).string()); 1842ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"), 184376327314d2238e105f8b94909f9c0cf85caca318Maurice Chu &error); 1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error != "") { 184576327314d2238e105f8b94909f9c0cf85caca318Maurice Chu // Try looking for a RESOURCE_ATTR 184676327314d2238e105f8b94909f9c0cf85caca318Maurice Chu error = ""; 1847ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski printResolvedResourceAttribute(res, tree, RESOURCE_ATTR, 184876327314d2238e105f8b94909f9c0cf85caca318Maurice Chu String8("resource"), &error); 1849ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (error != "") { 185010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 185110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:value' or " 185276327314d2238e105f8b94909f9c0cf85caca318Maurice Chu "'android:resource' attribute for " 185310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "meta-data: %s", error.string()); 1854ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright goto bail; 1855ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 1856ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } 185776327314d2238e105f8b94909f9c0cf85caca318Maurice Chu printf("\n"); 1858ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else if (withinSupportsInput && tag == "input-type") { 1859ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1860ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright if (name != "" && error == "") { 1861ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright supportedInput.add(name); 1862ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright } else { 186310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 186410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", 1865ec4fdec76f2916b91a69d979f400cd69a3812631Michael Wright error.string()); 1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 18692c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else if (withinFeatureGroup && tag == "uses-feature") { 1870694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski const String8 androidSchema("http://schemas.android.com/apk/res/android"); 1871d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski FeatureGroup& top = featureGroups.editTop(); 1872d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 1873ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error); 1874d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (name != "" && error == "") { 1875694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski Feature feature(true); 1876694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 1877694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski int32_t featureVers = AaptXml::getIntegerAttribute( 1878694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski tree, androidSchema.string(), "version", 0, &error); 1879694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski if (error == "") { 1880694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski feature.version = featureVers; 1881694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski } else { 1882694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 1883694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski "failed to read attribute 'android:version': %s", 1884694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski error.string()); 1885694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski goto bail; 1886694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski } 1887694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 1888694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski top.features.add(name, feature); 1889d3edfde51bd069a63e820282421d1a534fcf00ceAdam Lesinski addParentFeatures(&top, name); 1890694d0a7dfd281060c9f8d92a79bda1b7071affe3Adam Lesinski 1891d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } else { 1892ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR, 1893ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski &error); 1894d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (error == "") { 1895d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (vers > top.openGLESVersion) { 1896d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski top.openGLESVersion = vers; 1897d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 1898d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 18992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 1900a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 190194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (depth == 4) { 190294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (tag == "intent-filter") { 190394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasIntentFilter = true; 190494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski withinIntentFilter = true; 190594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actMainActivity = false; 190694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWidgetReceivers = false; 190794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actImeService = false; 190894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actWallpaperService = false; 190994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actAccessibilityService = false; 191094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actPrintService = false; 191194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actDeviceAdminEnabled = false; 191294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = false; 191394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = false; 19149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = false; 19159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = false; 1916eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = false; 19179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = false; 19189d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = false; 19199d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = false; 192094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else if (withinService && tag == "meta-data") { 1921ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); 192294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 192310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 192410de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute for " 192510de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "meta-data tag in service '%s': %s", serviceName.string(), 19265f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski error.string()); 192794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 192894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 192994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 193094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service" || 193194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski name == "android.nfc.cardemulation.off_host_apdu_service") { 193294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool offHost = true; 193394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (name == "android.nfc.cardemulation.host_apdu_service") { 193494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost = false; 193594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 193694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 1937ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 xmlPath = AaptXml::getResolvedAttribute(res, tree, 1938ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski RESOURCE_ATTR, &error); 193994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 194010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 194110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:resource' attribute for " 194210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "meta-data tag in service '%s': %s", 19435f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski serviceName.string(), error.string()); 194494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 194594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 194694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 194794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski Vector<String8> categories = getNfcAidCategories(assets, xmlPath, 194894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski offHost, &error); 194994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (error != "") { 195010de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 195110de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting AID category for service '%s'", 195294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski serviceName.string()); 195394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski goto bail; 195494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 195594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski 195694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski const size_t catLen = categories.size(); 195794fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski for (size_t i = 0; i < catLen; i++) { 195894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski bool paymentCategory = (categories[i] == "payment"); 195994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (offHost) { 196094fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaOffHostPaymentCategory |= paymentCategory; 196194fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } else { 196294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski hasMetaHostPaymentCategory |= paymentCategory; 196394fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 196494fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 196594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 196694fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 1967a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if ((depth == 5) && withinIntentFilter) { 1968a5018c900f126ee8424c82497f32983873db741bAdam Lesinski String8 action; 1969a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "action") { 1970ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski action = AaptXml::getAttribute(tree, NAME_ATTR, &error); 1971a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 197210de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 197310de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'android:name' attribute: %s", error.string()); 1974a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 1975a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 1976a5018c900f126ee8424c82497f32983873db741bAdam Lesinski 1977a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 1978a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.MAIN") { 1979a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isMainActivity = true; 1980a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actMainActivity = true; 19819d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA" || 19829d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski action == "android.media.action.VIDEO_CAMERA") { 19839d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCamera = true; 19849d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") { 19859d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actCameraSecure = true; 1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1987a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinReceiver) { 1988a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 1989a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWidgetReceivers = true; 1990a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") { 1991a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actDeviceAdminEnabled = true; 1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1993a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (withinService) { 1994a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.view.InputMethod") { 1995a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actImeService = true; 1996a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } else if (action == "android.service.wallpaper.WallpaperService") { 1997a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actWallpaperService = true; 19985f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (action == 19995f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.accessibilityservice.AccessibilityService") { 2000a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actAccessibilityService = true; 20015f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (action =="android.printservice.PrintService") { 2002a5018c900f126ee8424c82497f32983873db741bAdam Lesinski actPrintService = true; 20035f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (action == 20045f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { 200594fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actHostApduService = true; 20065f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (action == 20075f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { 200894fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski actOffHostApduService = true; 20095f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski } else if (action == 20105f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski "android.service.notification.NotificationListenerService") { 20119d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actNotificationListenerService = true; 2012eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } else if (action == "android.service.dreams.DreamService") { 2013eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock actDreamService = true; 20149d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 20159d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (withinProvider) { 20169d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (action == "android.content.action.DOCUMENTS_PROVIDER") { 20179d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski actDocumentsProvider = true; 2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2020a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (action == "android.intent.action.SEARCH") { 2021a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isSearchable = true; 2022a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 2023a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2025a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (tag == "category") { 2026ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error); 2027a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (error != "") { 202810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos(manifestFile, tree.getLineNumber()).error( 202910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski "ERROR getting 'name' attribute: %s", error.string()); 2030a5018c900f126ee8424c82497f32983873db741bAdam Lesinski goto bail; 2031a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 2032a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (withinActivity) { 2033a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (category == "android.intent.category.LAUNCHER") { 2034a5018c900f126ee8424c82497f32983873db741bAdam Lesinski isLauncherActivity = true; 20350a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn } else if (category == "android.intent.category.LEANBACK_LAUNCHER") { 20360a5a5d6996e54a927af750e122a1275d64f77ee5Tim Kilbourn isLeanbackLauncherActivity = true; 20379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } else if (category == "android.intent.category.HOME") { 20389d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski catLauncher = true; 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-1.6 implicitly granted permission compatibility logic 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 4) { 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteExternalStoragePermission) { 204858f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE")); 204958f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"), 205058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasWriteExternalStoragePermission = true; 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadPhoneStatePermission) { 205458f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_PHONE_STATE")); 205558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_PHONE_STATE"), 205658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 4")); 2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If the application has requested WRITE_EXTERNAL_STORAGE, we will 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // force them to always take READ_EXTERNAL_STORAGE as well. We always 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // do this (regardless of target API version) because we can't have 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // an app with write permission but not read permission. 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { 20652386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 20662386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski false /* optional */, writeExternalStoragePermissionMaxSdkVersion); 206758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"), 20682386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski String8("requested WRITE_EXTERNAL_STORAGE"), 20692386df23ac9e932a385b9c2fbddbf9e445eaada0Adam Lesinski writeExternalStoragePermissionMaxSdkVersion); 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Pre-JellyBean call log permission compatibility. 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (targetSdk < 16) { 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasReadCallLogPermission && hasReadContactsPermission) { 207558f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.READ_CALL_LOG")); 207658f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"), 207758f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested READ_CONTACTS")); 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hasWriteCallLogPermission && hasWriteContactsPermission) { 208058f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesPermission(String8("android.permission.WRITE_CALL_LOG")); 208158f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski printUsesImpliedPermission(String8("android.permission.WRITE_CALL_LOG"), 208258f1f3617cb6d96e3f3cf3d5c99004a362f0a61eAdam Lesinski String8("targetSdkVersion < 16 and requested WRITE_CONTACTS")); 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2086ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski // If the app hasn't declared the touchscreen as a feature requirement (either 2087ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski // directly or implied, required or not), then the faketouch feature is implied. 2088ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski if (!hasFeature("android.hardware.touchscreen", commonFeatures, impliedFeatures)) { 2089ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski addImpliedFeature(&impliedFeatures, "android.hardware.faketouch", 209043158773b469c2d5b23e52998d0afba9a4b34323Adam Lesinski String8("default feature for all apps"), false); 2091ca955a4c3ab3d4b83c6e9d5278bcd8d2258d44adAdam Lesinski } 20922c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 20932c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numFeatureGroups = featureGroups.size(); 20942c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (numFeatureGroups == 0) { 20952c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // If no <feature-group> tags were defined, apply auto-implied features. 20965f3b2ecb3e9d27e77bd59c7b9006a6239b773944Adam Lesinski printDefaultFeatureGroup(commonFeatures, impliedFeatures); 20972c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 20982c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } else { 20992c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // <feature-group> tags are defined, so we ignore implied features and 21002c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t i = 0; i < numFeatureGroups; i++) { 21012c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski FeatureGroup& grp = featureGroups.editItemAt(i); 21022c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 2103d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski if (commonFeatures.openGLESVersion > grp.openGLESVersion) { 2104d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.openGLESVersion = commonFeatures.openGLESVersion; 2105d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski } 2106d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski 21072c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // Merge the features defined in the top level (not inside a <feature-group>) 21082c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski // with this feature group. 21092c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski const size_t numCommonFeatures = commonFeatures.features.size(); 21102c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski for (size_t j = 0; j < numCommonFeatures; j++) { 21112c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski if (grp.features.indexOfKey(commonFeatures.features.keyAt(j)) < 0) { 2112d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski grp.features.add(commonFeatures.features.keyAt(j), 2113d7a94da476e9b783acf0673ed938cc3fc2cc6ba5Adam Lesinski commonFeatures.features[j]); 21142c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 2115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 211773a05114b051c6dcf5e5126ac94eaf8cac0ab289Adam Lesinski if (!grp.features.isEmpty()) { 21182c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski printFeatureGroup(grp); 21192c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski } 2120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21232c72b6822debb08fe997926eedc110f62d287d34Adam Lesinski 2124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWidgetReceivers) { 21259d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("app-widget"); 2126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2127a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasDeviceAdminReceiver) { 21289d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("device-admin"); 2129a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 2130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasImeService) { 21319d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("ime"); 2132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasWallpaperService) { 21349d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("wallpaper"); 2135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2136a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasAccessibilityService) { 21379d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("accessibility"); 2138a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 2139a5018c900f126ee8424c82497f32983873db741bAdam Lesinski if (hasPrintService) { 21409d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("print-service"); 2141a5018c900f126ee8424c82497f32983873db741bAdam Lesinski } 214294fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski if (hasPaymentService) { 21439d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("payment"); 21449d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 21459d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (isSearchable) { 21469d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("search"); 21479d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 21489d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasDocumentsProvider) { 21499d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("document-provider"); 21509d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 21519d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasLauncher) { 21529d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("launcher"); 21539d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 21549d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasNotificationListenerService) { 21559d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("notification-listener"); 21569d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 2157eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock if (hasDreamService) { 2158eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock printComponentPresence("dream"); 2159eb8d1be6acad180eabde84f19196b9ecaba81353John Spurlock } 21609d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraActivity) { 21619d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera"); 21629d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 21639d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasCameraSecureActivity) { 21649d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printComponentPresence("camera-secure"); 21659d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski } 21669d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski 21679d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasMainActivity) { 21689d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski printf("main\n"); 216994fc9124f51f0a101cc11e4563f9c647980fe2aaAdam Lesinski } 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherActivities) { 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-activities\n"); 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 21739d5b08ea8c1eef6658418b33090a6a8142d75208Adam Lesinski if (hasOtherReceivers) { 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-receivers\n"); 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasOtherServices) { 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("other-services\n"); 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For modern apps, if screen size buckets haven't been specified 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // but the new width ranges have, then infer the buckets from them. 2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && requiresSmallestWidthDp > 0) { 2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int compatWidth = compatibleWidthLimitDp; 2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatWidth <= 0) { 2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski compatWidth = requiresSmallestWidthDp; 2187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { 2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = -1; 2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = 0; 2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { 2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = 0; 2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { 2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = -1; 2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = 0; 2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { 2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = -1; 2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = 0; 2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Determine default values for any unspecified screen sizes, 2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // based on the target SDK of the package. As of 4 (donut) 2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the screen size support was introduced, so all default to 2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // enabled. 2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen > 0) { 2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski smallScreen = targetSdk >= 4 ? -1 : 0; 2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen > 0) { 2218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski normalScreen = -1; 2219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen > 0) { 2221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski largeScreen = targetSdk >= 4 ? -1 : 0; 2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen > 0) { 2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Introduced in Gingerbread. 2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlargeScreen = targetSdk >= 9 ? -1 : 0; 2226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (anyDensity > 0) { 2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 2229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || compatibleWidthLimitDp > 0) ? -1 : 0; 2230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-screens:"); 2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (smallScreen != 0) { 2233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'small'"); 2234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (normalScreen != 0) { 2236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'normal'"); 2237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largeScreen != 0) { 2239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'large'"); 2240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (xlargeScreen != 0) { 2242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" 'xlarge'"); 2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); 2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (requiresSmallestWidthDp > 0) { 2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); 2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (compatibleWidthLimitDp > 0) { 2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); 2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (largestWidthLimitDp > 0) { 2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("largest-width-limit:'%d'\n", largestWidthLimitDp); 2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("locales:"); 2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NL = locales.size(); 2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NL; i++) { 2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* localeStr = locales[i].string(); 2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localeStr == NULL || strlen(localeStr) == 0) { 2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localeStr = "--_--"; 2262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'", localeStr); 2264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("densities:"); 2268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t ND = densities.size(); 2269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<ND; i++) { 2270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%d'", densities[i]); 2271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir != NULL) { 2276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (dir->getFileCount() > 0) { 2277e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski SortedVector<String8> architectures; 2278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<dir->getFileCount(); i++) { 2279e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.add(ResTable::normalizeForOutput( 2280e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski dir->getFileName(i).string())); 2281e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2282e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2283e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski bool outputAltNativeCode = false; 2284e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // A multiArch package is one that contains 64-bit and 2285e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit versions of native code and expects 3rd-party 2286e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // apps to load these native code libraries. Since most 2287e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 64-bit systems also support 32-bit apps, the apps 2288e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // loading this multiArch package's code may be either 2289e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 32-bit or 64-bit. 2290e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (hasMultiArch) { 2291e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If this is a multiArch package, report the 64-bit 2292e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // version only. Then as a separate entry, report the 2293e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // rest. 2294e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // 2295e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // If we report the 32-bit architecture, this APK will 2296e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // be installed on a 32-bit device, causing a large waste 2297e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // of bandwidth and disk space. This assumes that 2298e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // the developer of the multiArch package has also 2299e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski // made a version that is 32-bit only. 2300e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 intel64("x86_64"); 2301e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski String8 arm64("arm64-v8a"); 2302e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski ssize_t index = architectures.indexOf(intel64); 2303e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index < 0) { 2304e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski index = architectures.indexOf(arm64); 2305e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2306e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2307e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (index >= 0) { 2308e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code: '%s'\n", architectures[index].string()); 2309e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski architectures.removeAt(index); 2310e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski outputAltNativeCode = true; 2311e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2312e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2313e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski 2314e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski const size_t archCount = architectures.size(); 2315e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (archCount > 0) { 2316e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski if (outputAltNativeCode) { 2317e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("alt-"); 2318e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2319e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("native-code:"); 2320e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski for (size_t i = 0; i < archCount; i++) { 2321e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf(" '%s'", architectures[i].string()); 2322e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski } 2323e47fd129057b19862e94b89f9ba413b5ceaca498Adam Lesinski printf("\n"); 2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete dir; 2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("badger", option) == 0) { 2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s", CONSOLE_DATA); 2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp("configurations", option) == 0) { 2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<ResTable_config> configs; 2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res.getConfigurations(&configs); 2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = configs.size(); 2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%s\n", configs[i].toString().string()); 2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 234610de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski if (SourcePos::hasErrors()) { 234710de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski SourcePos::printErrors(stderr); 234810de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski } 234910de3af152fc8612db08f3787fd17e70122b7486Adam Lesinski 2350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (asset) { 2351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete asset; 2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Handle the "add" command, which wants to add files to a new or 2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre-existing archive. 2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doAdd(Bundle* bundle) 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getUpdate()) { 2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* avoid confusion */ 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: can't use '-u' with add\n"); 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, true); 2385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 2387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'... (from gzip)\n", fileName); 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getJunkPath()) { 2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 storageName = String8(fileName).getPathLeaf(); 23992675f769673f69b0661ddee346292f25cb30a296Maurice Chu printf(" '%s' as '%s'...\n", fileName, 24002675f769673f69b0661ddee346292f25cb30a296Maurice Chu ResTable::normalizeForOutput(storageName.string()).string()); 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, storageName.string(), 2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getCompressionMethod(), NULL); 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s'...\n", fileName); 2405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 2406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 2410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result == NAME_NOT_FOUND) { 2411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": file not found\n"); 2412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (result == ALREADY_EXISTS) { 2413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, ": already exists in archive\n"); 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "\n"); 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = NO_ERROR; 2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delete files from an existing archive. 2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doRemove(Bundle* bundle) 2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipFile* zip = NULL; 2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = UNKNOWN_ERROR; 2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* zipFileName; 2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 1) { 2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: must specify zip file name\n"); 2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName = bundle->getFileSpecEntry(0); 2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getFileSpecCount() < 2) { 2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "NOTE: nothing to do\n"); 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip = openReadWrite(zipFileName, false); 2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (zip == NULL) { 2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zipFileName); 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < bundle->getFileSpecCount(); i++) { 2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* fileName = bundle->getFileSpecEntry(i); 2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ZipEntry* entry; 2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski entry = zip->getEntryByName(fileName); 2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry == NULL) { 2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" '%s' NOT FOUND\n", fileName); 2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = zip->remove(entry); 2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != NO_ERROR) { 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Unable to delete '%s' from '%s'\n", 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundle->getFileSpecEntry(i), zipFileName); 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* update the archive */ 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zip->flush(); 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete zip; 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (result != NO_ERROR); 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 24833921e87e6e67a063caa1987937d7944b24aef489Adam Lesinskistatic status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilder>& builder, bool ignoreConfig=false) { 2484fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numDirs = dir->getDirs().size(); 2485fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numDirs; i++) { 24863921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski bool ignore = ignoreConfig; 24873921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); 24883921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski const char* dirStr = subDir->getLeaf().string(); 24893921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (!ignore && strstr(dirStr, "mipmap") == dirStr) { 24903921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski ignore = true; 24913921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 24923921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = addResourcesToBuilder(subDir, builder, ignore); 2493fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2494fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2495fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2496fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2497fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2498fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numFiles = dir->getFiles().size(); 2499fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numFiles; i++) { 2500fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<AaptGroup> gp = dir->getFiles().valueAt(i); 2501fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numConfigs = gp->getFiles().size(); 2502fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t j = 0; j < numConfigs; j++) { 25033921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski status_t err = NO_ERROR; 25043921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski if (ignoreConfig) { 25053921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 25063921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } else { 25073921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); 25083921e87e6e67a063caa1987937d7944b24aef489Adam Lesinski } 2509fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2510fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Failed to add %s (%s) to builder.\n", 2511fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); 2512fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return err; 2513fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2514fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2515fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2516fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 2517fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2518fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2519fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatic String8 buildApkName(const String8& original, const sp<ApkSplit>& split) { 2520fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (split->isBase()) { 2521fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return original; 2522fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2523fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2524fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 ext(original.getPathExtension()); 2525fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (ext == String8(".apk")) { 2526fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s%s", 2527fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski original.getBasePath().string(), 2528fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string(), 2529fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ext.string()); 2530fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2531fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2532fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return String8::format("%s_%s", original.string(), 2533fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski split->getDirectorySafeName().string()); 2534fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski} 2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Package up an asset directory and associated application files. 2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doPackage(Bundle* bundle) 2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* outputAPKFile; 2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retVal = 1; 2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptAssets> assets; 2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int N; 2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FILE* fp; 2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 dependencyFile; 2548fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<ApkBuilder> builder; 2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2550a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // -c en_XA or/and ar_XB means do pseudolocalization 2551fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski sp<WeakResourceFilter> configFilter = new WeakResourceFilter(); 2552fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = configFilter->parse(bundle->getConfigurations()); 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2556fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudo()) { 2557a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); 2558a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 2559fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (configFilter->containsPseudoBidi()) { 2560a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = bundle->getFileSpecCount(); 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 256509384303dea4f3f01d5682918d7bab9bf83a02b1Adam Lesinski && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDirs().size() == 0) { 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: no input files\n"); 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile = bundle->getOutputAPKFile(); 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure the filenames provided exist and are of the appropriate type. 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski FileType type; 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = getFileType(outputAPKFile); 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "ERROR: output file '%s' exists but is not regular file\n", 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outputAPKFile); 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Load the assets. 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets = new AaptAssets(); 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set up the resource gathering in assets if we're going to generate 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dependency files. Every time we encounter a resource while slurping 2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the tree, we'll add it to these stores so we have full resource paths 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to write to a dependency file. 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> resPathStore = new FilePathStore; 2593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullResPaths(resPathStore); 2594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<FilePathStore> assetPathStore = new FilePathStore; 2595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->setFullAssetPaths(assetPathStore); 2596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = assets->slurpFromArgs(bundle); 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getVerbose()) { 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->print(String8()); 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2607fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Create the ApkBuilder, which will collect the compiled files 2608fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // to write to the final APK (or sets of APKs if we are building 2609fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // a Split APK. 2610fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski builder = new ApkBuilder(configFilter); 2611fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2612fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If we are generating a Split APK, find out which configurations to split on. 2613fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (bundle->getSplitConfigurations().size() > 0) { 2614fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<String8>& splitStrs = bundle->getSplitConfigurations(); 2615fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splitStrs.size(); 2616fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2617fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::set<ConfigDescription> configs; 2618fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parseCommaSeparatedList(splitStrs[i], &configs)) { 2619fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: failed to parse split configuration '%s'\n", splitStrs[i].string()); 2620fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2621fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2622fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2623fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = builder->createSplitForConfigs(configs); 2624fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2625fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2626fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2627fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2628fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2629fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If they asked for any fileAs that need to be compiled, do so. 2631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 2632fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = buildResources(bundle, assets, builder); 2633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != 0) { 2634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // At this point we've read everything and processed everything. From here 2639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // on out it's just writing output files. 2640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Update symbols with information about which ones are needed as Java symbols. 2645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assets->applyJavaSymbols(); 2646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, do that here 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is the packaging step, generate the dependency file next to 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the output apk (e.g. bin/resources.ap_.d) 2654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(outputAPKFile); 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Add the .d extension to the dependency file. 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.append(".d"); 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Else if this is the R.java dependency generation step, 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // generate the dependency file in the R.java package subdirectory 2661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java.d 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile = String8(bundle->getRClassDir()); 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dependencyFile.appendPath("R.java.d"); 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Make sure we have a clean dependency file to start with 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "w"); 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out R.java constants 2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!assets->havePrivateSymbols()) { 2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getCustomPackage() == NULL) { 2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file into the appropriate class directory 2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/R.java 26751e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), true, 2676a6d7e3fb9c9233b9ae46b702d17433854c43d6a0Tao Bai bundle->getBuildSharedLibrary() || bundle->getBuildAppAsSharedLibrary()); 2677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 customPkg(bundle->getCustomPackage()); 26791e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, customPkg, true, 2680a6d7e3fb9c9233b9ae46b702d17433854c43d6a0Tao Bai bundle->getBuildSharedLibrary() || bundle->getBuildAppAsSharedLibrary()); 2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we have library files, we're going to write our R.java file into 2686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the appropriate class directory for those libraries as well. 2687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // e.g. gen/com/foo/app/lib/R.java 2688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getExtraPackages() != NULL) { 2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Split on colon 2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 libs(bundle->getExtraPackages()); 2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); 2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (packageString != NULL) { 2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the R.java file out with the correct package name 26940f3a5a6559a955ea20f1ae2d3e0995f3fa821c90Marcin Kosiba err = writeResourceSymbols(bundle, assets, String8(packageString), true, 2695a6d7e3fb9c9233b9ae46b702d17433854c43d6a0Tao Bai bundle->getBuildSharedLibrary() || bundle->getBuildAppAsSharedLibrary()); 2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski packageString = strtok(NULL, ":"); 2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski libs.unlockBuffer(); 2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 27041e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false); 2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 27081e466385d4a4f1acee080fa0fdf16cc8fd8ce7caAdam Lesinski err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false); 2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write out the ProGuard file 2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeProguardFile(bundle, assets); 2716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < 0) { 2717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 272086229cb622fccde8ab8cbe85eead91a34313a708Rohit Agrawal // Write out the Main Dex ProGuard file 272186229cb622fccde8ab8cbe85eead91a34313a708Rohit Agrawal err = writeMainDexProguardFile(bundle, assets); 272286229cb622fccde8ab8cbe85eead91a34313a708Rohit Agrawal if (err < 0) { 272386229cb622fccde8ab8cbe85eead91a34313a708Rohit Agrawal goto bail; 272486229cb622fccde8ab8cbe85eead91a34313a708Rohit Agrawal } 272586229cb622fccde8ab8cbe85eead91a34313a708Rohit Agrawal 2726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the apk 2727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outputAPKFile) { 2728fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Gather all resources and add them to the APK Builder. The builder will then 2729fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // figure out which Split they belong in. 2730fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = addResourcesToBuilder(assets, builder); 2731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 2733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2734fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 2735fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const Vector<sp<ApkSplit> >& splits = builder->getSplits(); 2736fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t numSplits = splits.size(); 2737fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < numSplits; i++) { 2738fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const sp<ApkSplit>& split = splits[i]; 2739fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski String8 outputPath = buildApkName(String8(outputAPKFile), split); 2740fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski err = writeAPK(bundle, outputPath, split); 2741fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (err != NO_ERROR) { 2742fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputPath.string()); 2743fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski goto bail; 2744fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2745fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 2746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If we've been asked to generate a dependency file, we need to finish up here. 2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the writeResourceSymbols and writeAPK functions have already written the target 2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // half of the dependency file, now we need to write the prerequisites. (files that 2751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the R.java file or .ap_ file depend on) 2752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getGenDependencies()) { 2753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now that writeResourceSymbols or writeAPK has taken care of writing 2754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the targets to our dependency file, we'll write the prereqs 2755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fp = fopen(dependencyFile, "a+"); 2756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " : "); 2757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool includeRaw = (outputAPKFile != NULL); 2758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); 2759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Also manually add the AndroidManifeset since it's not under res/ or assets/ 2760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and therefore was not added to our pathstores during slurping 2761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); 2762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fclose(fp); 2763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retVal = 0; 2766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 2767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (SourcePos::hasErrors()) { 2768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos::printErrors(stderr); 2769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return retVal; 2771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching 2775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * PRECONDITIONS 2776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -S flag points to a source directory containing drawable* folders 2777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -C flag points to destination directory. The folder structure in the 2778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * source directory will be mirrored to the destination (cache) directory 2779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * POSTCONDITIONS 2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Destination directory will be updated to match the PNG files in 27822675f769673f69b0661ddee346292f25cb30a296Maurice Chu * the source directory. 2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doCrunch(Bundle* bundle) 2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching PNG Files in "); 2787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); 2788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); 2789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski updatePreProcessedCache(bundle); 2791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Do PNG Crunching on a single flag 2797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -i points to a single png file 2798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * -o points to a single png output file 2799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint doSingleCrunch(Bundle* bundle) 2801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); 2803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); 2804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 input(bundle->getSingleCrunchInputFile()); 2806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 output(bundle->getSingleCrunchOutputFile()); 2807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { 2809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we can't return the status_t as it gets truncate to the lower 8 bits. 2810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 42; 2811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 28166f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochezint runInDaemonMode(Bundle* bundle) { 28176f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Ready" << std::endl; 2818de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington for (std::string cmd; std::getline(std::cin, cmd);) { 2819de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington if (cmd == "quit") { 28206f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez return NO_ERROR; 2821de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington } else if (cmd == "s") { 2822de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington // Two argument crunch 2823de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington std::string inputFile, outputFile; 2824de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington std::getline(std::cin, inputFile); 2825de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington std::getline(std::cin, outputFile); 2826de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington bundle->setSingleCrunchInputFile(inputFile.c_str()); 2827de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington bundle->setSingleCrunchOutputFile(outputFile.c_str()); 2828de3ab0a9e8609f6a631b2c047f352069bb9cfa86Chris Warrington std::cout << "Crunching " << inputFile << std::endl; 28296f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez if (doSingleCrunch(bundle) != NO_ERROR) { 28306f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Error" << std::endl; 28316f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 28326f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cout << "Done" << std::endl; 28336f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } else { 28346f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez // in case of invalid command, just bail out. 28356f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez std::cerr << "Unknown command" << std::endl; 28366f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez return -1; 28376f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 28386f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez } 28396f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez return -1; 28406f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez} 28416f1280cf170b358a57ff70341a9f2ad224e5a662Jerome Dochez 2842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskichar CONSOLE_DATA[2925] = { 2843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 2848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 2849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 2852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, 2853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, 2856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 2859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, 2860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 2863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 2864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 2867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 2870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 2871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, 2874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, 2877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, 2878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 2881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 2882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 2885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 2888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 2889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, 2891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, 2892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, 2894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, 2895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, 2896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, 2899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 2900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 2901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 2903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 2904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 2905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 2906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 2907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 2909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, 2910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 2911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, 2912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, 2913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, 2914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, 2915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 2917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 2919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 2921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 2922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 2924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 2925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, 2926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 2929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 2931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 2932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 2935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 2936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 2941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 2942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 2943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, 2946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 2947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 2948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, 2950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, 2953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 2954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 2959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 2960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 2961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, 2964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 2965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 2966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 2967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, 2968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 2969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 2970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, 2971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, 2972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 2975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 2976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 2977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 2978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 2979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, 2983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 2984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, 2986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 2988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 2989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, 2990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 2993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 2994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 2995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 2996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 2997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 3000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 3001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 3002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 3003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 3004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 3005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 3006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 3007