Command.cpp revision 6919f69281e32d0c3d4b3791b273f71f178cbb7c
15778822d86b0337407514b9372562b86edfa91cdAndreas Huber// 25778822d86b0337407514b9372562b86edfa91cdAndreas Huber// Copyright 2006 The Android Open Source Project 35778822d86b0337407514b9372562b86edfa91cdAndreas Huber// 45778822d86b0337407514b9372562b86edfa91cdAndreas Huber// Android Asset Packaging Tool main entry point. 55778822d86b0337407514b9372562b86edfa91cdAndreas Huber// 65778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include "Main.h" 75778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include "Bundle.h" 85778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include "ResourceTable.h" 95778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include "XMLNode.h" 105778822d86b0337407514b9372562b86edfa91cdAndreas Huber 115778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <utils/Log.h> 125778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <utils/threads.h> 135778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <utils/List.h> 145778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <utils/Errors.h> 155778822d86b0337407514b9372562b86edfa91cdAndreas Huber 165778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <fcntl.h> 175778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <errno.h> 185778822d86b0337407514b9372562b86edfa91cdAndreas Huber 195778822d86b0337407514b9372562b86edfa91cdAndreas Huberusing namespace android; 205778822d86b0337407514b9372562b86edfa91cdAndreas Huber 215778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 225778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Show version info. All the cool kids do it. 235778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 245778822d86b0337407514b9372562b86edfa91cdAndreas Huberint doVersion(Bundle* bundle) 251a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian{ 26ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (bundle->getFileSpecCount() != 0) 275778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("(ignoring extra arguments)\n"); 285778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("Android Asset Packaging Tool, v0.2\n"); 295778822d86b0337407514b9372562b86edfa91cdAndreas Huber 305b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return 0; 31ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber} 325778822d86b0337407514b9372562b86edfa91cdAndreas Huber 337cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 345778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 355778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Open the file read only. The call fails if the file doesn't exist. 365778822d86b0337407514b9372562b86edfa91cdAndreas Huber * 375778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Returns NULL on failure. 385778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 395778822d86b0337407514b9372562b86edfa91cdAndreas HuberZipFile* openReadOnly(const char* fileName) 405778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 415778822d86b0337407514b9372562b86edfa91cdAndreas Huber ZipFile* zip; 425778822d86b0337407514b9372562b86edfa91cdAndreas Huber status_t result; 435778822d86b0337407514b9372562b86edfa91cdAndreas Huber 445778822d86b0337407514b9372562b86edfa91cdAndreas Huber zip = new ZipFile; 455778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = zip->open(fileName, ZipFile::kOpenReadOnly); 465778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (result != NO_ERROR) { 475778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (result == NAME_NOT_FOUND) 485778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: '%s' not found\n", fileName); 495778822d86b0337407514b9372562b86edfa91cdAndreas Huber else if (result == PERMISSION_DENIED) 505778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: '%s' access denied\n", fileName); 515778822d86b0337407514b9372562b86edfa91cdAndreas Huber else 525778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", 535778822d86b0337407514b9372562b86edfa91cdAndreas Huber fileName); 545778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete zip; 555778822d86b0337407514b9372562b86edfa91cdAndreas Huber return NULL; 565778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 575778822d86b0337407514b9372562b86edfa91cdAndreas Huber 585778822d86b0337407514b9372562b86edfa91cdAndreas Huber return zip; 595778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 605778822d86b0337407514b9372562b86edfa91cdAndreas Huber 615778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 625778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Open the file read-write. The file will be created if it doesn't 635778822d86b0337407514b9372562b86edfa91cdAndreas Huber * already exist and "okayToCreate" is set. 645778822d86b0337407514b9372562b86edfa91cdAndreas Huber * 655778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Returns NULL on failure. 667cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden */ 675778822d86b0337407514b9372562b86edfa91cdAndreas HuberZipFile* openReadWrite(const char* fileName, bool okayToCreate) 685778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 695778822d86b0337407514b9372562b86edfa91cdAndreas Huber ZipFile* zip = NULL; 705778822d86b0337407514b9372562b86edfa91cdAndreas Huber status_t result; 715778822d86b0337407514b9372562b86edfa91cdAndreas Huber int flags; 726507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden 736507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden flags = ZipFile::kOpenReadWrite; 745778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (okayToCreate) 755778822d86b0337407514b9372562b86edfa91cdAndreas Huber flags |= ZipFile::kOpenCreate; 765778822d86b0337407514b9372562b86edfa91cdAndreas Huber 775778822d86b0337407514b9372562b86edfa91cdAndreas Huber zip = new ZipFile; 785778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = zip->open(fileName, flags); 795778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (result != NO_ERROR) { 805778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete zip; 815778822d86b0337407514b9372562b86edfa91cdAndreas Huber zip = NULL; 825778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 835778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 845778822d86b0337407514b9372562b86edfa91cdAndreas Huber 855778822d86b0337407514b9372562b86edfa91cdAndreas Huberbail: 865778822d86b0337407514b9372562b86edfa91cdAndreas Huber return zip; 875778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 885778822d86b0337407514b9372562b86edfa91cdAndreas Huber 895778822d86b0337407514b9372562b86edfa91cdAndreas Huber 905778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 915778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Return a short string describing the compression method. 925778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 935778822d86b0337407514b9372562b86edfa91cdAndreas Huberconst char* compressionName(int method) 945778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 955778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (method == ZipEntry::kCompressStored) 965778822d86b0337407514b9372562b86edfa91cdAndreas Huber return "Stored"; 975778822d86b0337407514b9372562b86edfa91cdAndreas Huber else if (method == ZipEntry::kCompressDeflated) 985778822d86b0337407514b9372562b86edfa91cdAndreas Huber return "Deflated"; 995778822d86b0337407514b9372562b86edfa91cdAndreas Huber else 1005778822d86b0337407514b9372562b86edfa91cdAndreas Huber return "Unknown"; 1015778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1025778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1035778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 1045778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Return the percent reduction in size (0% == no compression). 1055778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 1065778822d86b0337407514b9372562b86edfa91cdAndreas Huberint calcPercent(long uncompressedLen, long compressedLen) 1075778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 1085778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!uncompressedLen) 1095778822d86b0337407514b9372562b86edfa91cdAndreas Huber return 0; 1105778822d86b0337407514b9372562b86edfa91cdAndreas Huber else 1115778822d86b0337407514b9372562b86edfa91cdAndreas Huber return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); 1125778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1135778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1145778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 1155778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Handle the "list" command, which can be a simple file dump or 1165778822d86b0337407514b9372562b86edfa91cdAndreas Huber * a verbose listing. 1175778822d86b0337407514b9372562b86edfa91cdAndreas Huber * 1185778822d86b0337407514b9372562b86edfa91cdAndreas Huber * The verbose listing closely matches the output of the Info-ZIP "unzip" 1195778822d86b0337407514b9372562b86edfa91cdAndreas Huber * command. 1205778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 1215778822d86b0337407514b9372562b86edfa91cdAndreas Huberint doList(Bundle* bundle) 1225778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 1235778822d86b0337407514b9372562b86edfa91cdAndreas Huber int result = 1; 1245778822d86b0337407514b9372562b86edfa91cdAndreas Huber ZipFile* zip = NULL; 1255778822d86b0337407514b9372562b86edfa91cdAndreas Huber const ZipEntry* entry; 1265778822d86b0337407514b9372562b86edfa91cdAndreas Huber long totalUncLen, totalCompLen; 1275778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* zipFileName; 1285778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1295778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getFileSpecCount() != 1) { 1305778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: specify zip file name (only)\n"); 1315778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 1325778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1335778822d86b0337407514b9372562b86edfa91cdAndreas Huber zipFileName = bundle->getFileSpecEntry(0); 1345778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1355778822d86b0337407514b9372562b86edfa91cdAndreas Huber zip = openReadOnly(zipFileName); 1365778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (zip == NULL) 1375778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 1381a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian 1391bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber int count, i; 1405778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1415778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getVerbose()) { 1425778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("Archive: %s\n", zipFileName); 1435778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf( 1445778822d86b0337407514b9372562b86edfa91cdAndreas Huber " Length Method Size Ratio Date Time CRC-32 Name\n"); 1455778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf( 1465778822d86b0337407514b9372562b86edfa91cdAndreas Huber "-------- ------ ------- ----- ---- ---- ------ ----\n"); 1471bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 1481bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 1491bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber totalUncLen = totalCompLen = 0; 1501bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 1511bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber count = zip->getNumEntries(); 1521bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber for (i = 0; i < count; i++) { 1531bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber entry = zip->getEntryByIndex(i); 1545778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getVerbose()) { 1555778822d86b0337407514b9372562b86edfa91cdAndreas Huber char dateBuf[32]; 1565778822d86b0337407514b9372562b86edfa91cdAndreas Huber time_t when; 1575778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1585778822d86b0337407514b9372562b86edfa91cdAndreas Huber when = entry->getModWhen(); 1595778822d86b0337407514b9372562b86edfa91cdAndreas Huber strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", 1607cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden localtime(&when)); 1617cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 1627cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf("%8ld %-7.7s %7ld %3d%% %s %08lx %s\n", 1637cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden (long) entry->getUncompressedLen(), 1647cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden compressionName(entry->getCompressionMethod()), 1657cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden (long) entry->getCompressedLen(), 1667cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden calcPercent(entry->getUncompressedLen(), 1677cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden entry->getCompressedLen()), 1687cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden dateBuf, 1697cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden entry->getCRC32(), 1707cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden entry->getFileName()); 1717cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } else { 1727cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf("%s\n", entry->getFileName()); 1737cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 1747cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 1757cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden totalUncLen += entry->getUncompressedLen(); 1767cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden totalCompLen += entry->getCompressedLen(); 1777cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 1787cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 1797cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (bundle->getVerbose()) { 1805778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf( 1815778822d86b0337407514b9372562b86edfa91cdAndreas Huber "-------- ------- --- -------\n"); 1825778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("%8ld %7ld %2d%% %d files\n", 1835778822d86b0337407514b9372562b86edfa91cdAndreas Huber totalUncLen, 1845778822d86b0337407514b9372562b86edfa91cdAndreas Huber totalCompLen, 1855778822d86b0337407514b9372562b86edfa91cdAndreas Huber calcPercent(totalUncLen, totalCompLen), 1865778822d86b0337407514b9372562b86edfa91cdAndreas Huber zip->getNumEntries()); 1875778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1885778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1895778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getAndroidList()) { 1905778822d86b0337407514b9372562b86edfa91cdAndreas Huber AssetManager assets; 1915778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!assets.addAssetPath(String8(zipFileName), NULL)) { 1925778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); 1935778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 194c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 195c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 196c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber const ResTable& res = assets.getResources(false); 197c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (&res == NULL) { 198c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber printf("\nNo resource table found.\n"); 199c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } else { 200c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber printf("\nResource table:\n"); 2015778822d86b0337407514b9372562b86edfa91cdAndreas Huber res.print(false); 2025778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2035778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2045778822d86b0337407514b9372562b86edfa91cdAndreas Huber Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", 2055778822d86b0337407514b9372562b86edfa91cdAndreas Huber Asset::ACCESS_BUFFER); 2065b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if (manifestAsset == NULL) { 2075b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber printf("\nNo AndroidManifest.xml found.\n"); 2085b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber } else { 2095b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber printf("\nAndroid manifest:\n"); 2105b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber ResXMLTree tree; 2115b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber tree.setTo(manifestAsset->getBuffer(true), 2125778822d86b0337407514b9372562b86edfa91cdAndreas Huber manifestAsset->getLength()); 2135778822d86b0337407514b9372562b86edfa91cdAndreas Huber printXMLBlock(&tree); 2145778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2155778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete manifestAsset; 2165778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2175778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2185b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber result = 0; 2195778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2205778822d86b0337407514b9372562b86edfa91cdAndreas Huberbail: 2215778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete zip; 2225778822d86b0337407514b9372562b86edfa91cdAndreas Huber return result; 2235778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 2244b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 2254b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huberstatic ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) 2264b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber{ 2274b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber size_t N = tree.getAttributeCount(); 2284b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber for (size_t i=0; i<N; i++) { 2294b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (tree.getAttributeNameResID(i) == attrRes) { 2304b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber return (ssize_t)i; 2314b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 2324b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 2335b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return -1; 2345b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber} 2355b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber 2365b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huberstatic String8 getAttribute(const ResXMLTree& tree, const char* ns, 2375b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber const char* attr, String8* outError) 2385b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber{ 2394b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber ssize_t idx = tree.indexOfAttribute(ns, attr); 2404b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (idx < 0) { 2414b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber return String8(); 2424b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 2434b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber Res_value value; 2444b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 2454b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (value.dataType != Res_value::TYPE_STRING) { 2464b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (outError != NULL) *outError = "attribute is not a string value"; 2474b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber return String8(); 2484b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 2495b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber } 2504b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber size_t len; 2514b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber const uint16_t* str = tree.getAttributeStringValue(idx, &len); 2525b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return str ? String8(str, len) : String8(); 2535b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber} 2545b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber 2554b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huberstatic String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) 2564b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber{ 2575778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t idx = indexOfAttribute(tree, attrRes); 2585778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (idx < 0) { 2595778822d86b0337407514b9372562b86edfa91cdAndreas Huber return String8(); 2605778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2615778822d86b0337407514b9372562b86edfa91cdAndreas Huber Res_value value; 2625778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 2635778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (value.dataType != Res_value::TYPE_STRING) { 2645778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (outError != NULL) *outError = "attribute is not a string value"; 2655778822d86b0337407514b9372562b86edfa91cdAndreas Huber return String8(); 2665778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2675778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2685778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t len; 2695778822d86b0337407514b9372562b86edfa91cdAndreas Huber const uint16_t* str = tree.getAttributeStringValue(idx, &len); 2705778822d86b0337407514b9372562b86edfa91cdAndreas Huber return str ? String8(str, len) : String8(); 2715778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 2725778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2735778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, 2745778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8* outError, int32_t defValue = -1) 2755778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 2765778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t idx = indexOfAttribute(tree, attrRes); 2775778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (idx < 0) { 2785778822d86b0337407514b9372562b86edfa91cdAndreas Huber return defValue; 2795778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2805778822d86b0337407514b9372562b86edfa91cdAndreas Huber Res_value value; 2815778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 2825778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (value.dataType < Res_value::TYPE_FIRST_INT 2835778822d86b0337407514b9372562b86edfa91cdAndreas Huber || value.dataType > Res_value::TYPE_LAST_INT) { 2845778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (outError != NULL) *outError = "attribute is not an integer value"; 2855778822d86b0337407514b9372562b86edfa91cdAndreas Huber return defValue; 2865778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2875778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2885778822d86b0337407514b9372562b86edfa91cdAndreas Huber return value.data; 2895778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 2905778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2915778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree, 2925778822d86b0337407514b9372562b86edfa91cdAndreas Huber uint32_t attrRes, String8* outError) 2935778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 2945778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t idx = indexOfAttribute(tree, attrRes); 2955778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (idx < 0) { 2965778822d86b0337407514b9372562b86edfa91cdAndreas Huber return String8(); 2975778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2985778822d86b0337407514b9372562b86edfa91cdAndreas Huber Res_value value; 2995778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 3005778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (value.dataType == Res_value::TYPE_STRING) { 3015778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t len; 3025778822d86b0337407514b9372562b86edfa91cdAndreas Huber const uint16_t* str = tree.getAttributeStringValue(idx, &len); 3035778822d86b0337407514b9372562b86edfa91cdAndreas Huber return str ? String8(str, len) : String8(); 3045778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3055778822d86b0337407514b9372562b86edfa91cdAndreas Huber resTable->resolveReference(&value, 0); 3065778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (value.dataType != Res_value::TYPE_STRING) { 3075778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (outError != NULL) *outError = "attribute is not a string value"; 3085778822d86b0337407514b9372562b86edfa91cdAndreas Huber return String8(); 3095778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3105778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3115778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t len; 3125778822d86b0337407514b9372562b86edfa91cdAndreas Huber const Res_value* value2 = &value; 3135778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len); 3147cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden return str ? String8(str, len) : String8(); 3157cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden} 3167cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 3177cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden// These are attribute resource constants for the platform, as found 3187cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden// in android.R.attr 3197cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenenum { 3207cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden NAME_ATTR = 0x01010003, 3215778822d86b0337407514b9372562b86edfa91cdAndreas Huber VERSION_CODE_ATTR = 0x0101021b, 3225778822d86b0337407514b9372562b86edfa91cdAndreas Huber VERSION_NAME_ATTR = 0x0101021c, 3235778822d86b0337407514b9372562b86edfa91cdAndreas Huber LABEL_ATTR = 0x01010001, 3245778822d86b0337407514b9372562b86edfa91cdAndreas Huber ICON_ATTR = 0x01010002, 3255778822d86b0337407514b9372562b86edfa91cdAndreas Huber MIN_SDK_VERSION_ATTR = 0x0101020c, 3265778822d86b0337407514b9372562b86edfa91cdAndreas Huber MAX_SDK_VERSION_ATTR = 0x01010271, 3275778822d86b0337407514b9372562b86edfa91cdAndreas Huber REQ_TOUCH_SCREEN_ATTR = 0x01010227, 3285778822d86b0337407514b9372562b86edfa91cdAndreas Huber REQ_KEYBOARD_TYPE_ATTR = 0x01010228, 3295778822d86b0337407514b9372562b86edfa91cdAndreas Huber REQ_HARD_KEYBOARD_ATTR = 0x01010229, 3305778822d86b0337407514b9372562b86edfa91cdAndreas Huber REQ_NAVIGATION_ATTR = 0x0101022a, 3315778822d86b0337407514b9372562b86edfa91cdAndreas Huber REQ_FIVE_WAY_NAV_ATTR = 0x01010232, 3325778822d86b0337407514b9372562b86edfa91cdAndreas Huber TARGET_SDK_VERSION_ATTR = 0x01010270, 3335778822d86b0337407514b9372562b86edfa91cdAndreas Huber TEST_ONLY_ATTR = 0x01010272, 3345778822d86b0337407514b9372562b86edfa91cdAndreas Huber DENSITY_ATTR = 0x0101026c, 335717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo SMALL_SCREEN_ATTR = 0x01010284, 336717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo NORMAL_SCREEN_ATTR = 0x01010285, 337717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo LARGE_SCREEN_ATTR = 0x01010286, 338717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo}; 339717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo 340717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjoconst char *getComponentName(String8 &pkgName, String8 &componentName) { 341717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo ssize_t idx = componentName.find("."); 342717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo String8 retStr(pkgName); 343717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo if (idx == 0) { 344717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo retStr += componentName; 345717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } else if (idx < 0) { 346717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo retStr += "."; 347717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo retStr += componentName; 348717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } else { 3495778822d86b0337407514b9372562b86edfa91cdAndreas Huber return componentName.string(); 3505778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3515778822d86b0337407514b9372562b86edfa91cdAndreas Huber return retStr.string(); 3525778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 3535778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3545778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 3555778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Handle the "dump" command, to extract select data from an archive. 3565778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 3575778822d86b0337407514b9372562b86edfa91cdAndreas Huberint doDump(Bundle* bundle) 3585778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 3595778822d86b0337407514b9372562b86edfa91cdAndreas Huber status_t result = UNKNOWN_ERROR; 3605778822d86b0337407514b9372562b86edfa91cdAndreas Huber Asset* asset = NULL; 3615778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3625778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getFileSpecCount() < 1) { 3635778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: no dump option specified\n"); 3645778822d86b0337407514b9372562b86edfa91cdAndreas Huber return 1; 3655778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3665778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3675778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getFileSpecCount() < 2) { 3685778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: no dump file specified\n"); 3695778822d86b0337407514b9372562b86edfa91cdAndreas Huber return 1; 3705778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3715778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3725778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* option = bundle->getFileSpecEntry(0); 3735778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* filename = bundle->getFileSpecEntry(1); 374496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber 375496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber AssetManager assets; 376496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber void* assetsCookie; 377496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber if (!assets.addAssetPath(String8(filename), &assetsCookie)) { 378496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); 379496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber return 1; 380575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber } 381575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 382575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber const ResTable& res = assets.getResources(false); 383575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (&res == NULL) { 384575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); 385575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber goto bail; 3865778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3875778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3885778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (strcmp("resources", option) == 0) { 3895778822d86b0337407514b9372562b86edfa91cdAndreas Huber res.print(bundle->getValues()); 3905778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3915778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (strcmp("xmltree", option) == 0) { 3925778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getFileSpecCount() < 3) { 3935778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 3945778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 3955778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3965778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3975778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (int i=2; i<bundle->getFileSpecCount(); i++) { 3985778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* resname = bundle->getFileSpecEntry(i); 3995778822d86b0337407514b9372562b86edfa91cdAndreas Huber ResXMLTree tree; 4005778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER); 4015778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (asset == NULL) { 4025778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: dump failed because resource %p found\n", resname); 4035778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4045778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4055778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4065778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tree.setTo(asset->getBuffer(true), 4075778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset->getLength()) != NO_ERROR) { 4085778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 4095778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4105778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4115778822d86b0337407514b9372562b86edfa91cdAndreas Huber tree.restart(); 4125778822d86b0337407514b9372562b86edfa91cdAndreas Huber printXMLBlock(&tree); 4135778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete asset; 4145778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset = NULL; 4155778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4165778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4175778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (strcmp("xmlstrings", option) == 0) { 4185778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getFileSpecCount() < 3) { 4195778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); 4205778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4215778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4225778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4235778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (int i=2; i<bundle->getFileSpecCount(); i++) { 4245778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* resname = bundle->getFileSpecEntry(i); 4255778822d86b0337407514b9372562b86edfa91cdAndreas Huber ResXMLTree tree; 4265778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER); 4275778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (asset == NULL) { 4285778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: dump failed because resource %p found\n", resname); 4295778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4305778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4315778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4325778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tree.setTo(asset->getBuffer(true), 4335778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset->getLength()) != NO_ERROR) { 4345778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); 4355778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4365778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4375778822d86b0337407514b9372562b86edfa91cdAndreas Huber printStringPool(&tree.getStrings()); 4385778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete asset; 4395778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset = NULL; 4405778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4415778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4425778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 4435778822d86b0337407514b9372562b86edfa91cdAndreas Huber ResXMLTree tree; 4445778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset = assets.openNonAsset("AndroidManifest.xml", 4455778822d86b0337407514b9372562b86edfa91cdAndreas Huber Asset::ACCESS_BUFFER); 4465778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (asset == NULL) { 4475778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); 4485778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4495778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4505778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4515778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tree.setTo(asset->getBuffer(true), 4525778822d86b0337407514b9372562b86edfa91cdAndreas Huber asset->getLength()) != NO_ERROR) { 4535778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); 4545778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4555778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4565778822d86b0337407514b9372562b86edfa91cdAndreas Huber tree.restart(); 4575778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4585778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (strcmp("permissions", option) == 0) { 4595778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t len; 4605778822d86b0337407514b9372562b86edfa91cdAndreas Huber ResXMLTree::event_code_t code; 4615778822d86b0337407514b9372562b86edfa91cdAndreas Huber int depth = 0; 4625778822d86b0337407514b9372562b86edfa91cdAndreas Huber while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 4635778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (code == ResXMLTree::END_TAG) { 4645778822d86b0337407514b9372562b86edfa91cdAndreas Huber depth--; 4655778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 4665778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4675778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (code != ResXMLTree::START_TAG) { 4685778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 4695778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4705778822d86b0337407514b9372562b86edfa91cdAndreas Huber depth++; 4715778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 tag(tree.getElementName(&len)); 4725778822d86b0337407514b9372562b86edfa91cdAndreas Huber //printf("Depth %d tag %s\n", depth, tag.string()); 4735778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (depth == 1) { 4745778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tag != "manifest") { 4755778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 4765778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4775778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4785778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 pkg = getAttribute(tree, NULL, "package", NULL); 4795778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("package: %s\n", pkg.string()); 4805778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (depth == 2 && tag == "permission") { 4815778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 error; 4825778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 name = getAttribute(tree, NAME_ATTR, &error); 4835778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 4845778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: %s\n", error.string()); 4855778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4865778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4875778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("permission: %s\n", name.string()); 4885778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (depth == 2 && tag == "uses-permission") { 4895778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 error; 4905778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 name = getAttribute(tree, NAME_ATTR, &error); 4915778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 4925778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: %s\n", error.string()); 4935778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 4945778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4955778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("uses-permission: %s\n", name.string()); 4965778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4975778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4985778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (strcmp("badging", option) == 0) { 4995778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t len; 5005778822d86b0337407514b9372562b86edfa91cdAndreas Huber ResXMLTree::event_code_t code; 5015778822d86b0337407514b9372562b86edfa91cdAndreas Huber int depth = 0; 5025778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 error; 5035778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool withinActivity = false; 5045778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool isMainActivity = false; 5055778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool isLauncherActivity = false; 5065778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool withinApplication = false; 5075778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool withinReceiver = false; 5085778822d86b0337407514b9372562b86edfa91cdAndreas Huber int targetSdk = 0; 5095778822d86b0337407514b9372562b86edfa91cdAndreas Huber int smallScreen = 1; 5105778822d86b0337407514b9372562b86edfa91cdAndreas Huber int normalScreen = 1; 5115778822d86b0337407514b9372562b86edfa91cdAndreas Huber int largeScreen = 1; 5125778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 pkg; 5135778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 activityName; 5145778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 activityLabel; 5155778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 activityIcon; 5165778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 receiverName; 5175778822d86b0337407514b9372562b86edfa91cdAndreas Huber while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 5185778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (code == ResXMLTree::END_TAG) { 5195778822d86b0337407514b9372562b86edfa91cdAndreas Huber depth--; 5205778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 5215778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5225778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (code != ResXMLTree::START_TAG) { 5235778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 5245778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5255778822d86b0337407514b9372562b86edfa91cdAndreas Huber depth++; 5265778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 tag(tree.getElementName(&len)); 5275778822d86b0337407514b9372562b86edfa91cdAndreas Huber //printf("Depth %d tag %s\n", depth, tag.string()); 5285778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (depth == 1) { 5295778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tag != "manifest") { 5305778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); 531c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber goto bail; 5325778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5335778822d86b0337407514b9372562b86edfa91cdAndreas Huber pkg = getAttribute(tree, NULL, "package", NULL); 5345778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("package: name='%s' ", pkg.string()); 5355778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error); 5365778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 5375778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string()); 5385778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 5395778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5405778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (versionCode > 0) { 5415778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("versionCode='%d' ", versionCode); 5425778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 5435778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("versionCode='' "); 5445778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5455778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 versionName = getAttribute(tree, VERSION_NAME_ATTR, &error); 5465778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 5475778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); 5485778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 5495778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5505778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("versionName='%s'\n", versionName.string()); 551575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber } else if (depth == 2) { 5525778822d86b0337407514b9372562b86edfa91cdAndreas Huber withinApplication = false; 5535778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tag == "application") { 5545778822d86b0337407514b9372562b86edfa91cdAndreas Huber withinApplication = true; 5555778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 5565778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 5575778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string()); 5585778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 5595778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5605778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("application: label='%s' ", label.string()); 5615778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 562575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (error != "") { 5635778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); 5645778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 5655778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5665778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("icon='%s'\n", icon.string()); 5675778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0); 5685778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 5695778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string()); 5705778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 5715778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5725778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (testOnly != 0) { 5735778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("testOnly='%d'\n", testOnly); 5745778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5755778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (tag == "uses-sdk") { 5765778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); 5775778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 5785778822d86b0337407514b9372562b86edfa91cdAndreas Huber error = ""; 5795778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error); 5805778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 581717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", 5825778822d86b0337407514b9372562b86edfa91cdAndreas Huber error.string()); 583717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo goto bail; 5845778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5855778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (name == "Donut") targetSdk = 4; 5865778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("sdkVersion:'%s'\n", name.string()); 5875778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (code != -1) { 5885778822d86b0337407514b9372562b86edfa91cdAndreas Huber targetSdk = code; 589717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo printf("sdkVersion:'%d'\n", code); 5901bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 5911bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1); 5921bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber if (code != -1) { 5931bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber printf("maxSdkVersion:'%d'\n", code); 5941bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 5955778822d86b0337407514b9372562b86edfa91cdAndreas Huber code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); 5965778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 5975778822d86b0337407514b9372562b86edfa91cdAndreas Huber error = ""; 5985778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error); 5995778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 6005778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", 6015778822d86b0337407514b9372562b86edfa91cdAndreas Huber error.string()); 6025778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 6035778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6046507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden if (name == "Donut" && targetSdk < 4) targetSdk = 4; 6056507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden printf("targetSdkVersion:'%s'\n", name.string()); 6066507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden } else if (code != -1) { 6075778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (targetSdk < code) { 6085778822d86b0337407514b9372562b86edfa91cdAndreas Huber targetSdk = code; 6095778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6105778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("targetSdkVersion:'%d'\n", code); 6117cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 6127cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } else if (tag == "uses-configuration") { 6137cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int32_t reqTouchScreen = getIntegerAttribute(tree, 6147cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden REQ_TOUCH_SCREEN_ATTR, NULL, 0); 6157cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int32_t reqKeyboardType = getIntegerAttribute(tree, 6167cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden REQ_KEYBOARD_TYPE_ATTR, NULL, 0); 6177cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int32_t reqHardKeyboard = getIntegerAttribute(tree, 6187cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden REQ_HARD_KEYBOARD_ATTR, NULL, 0); 6197cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int32_t reqNavigation = getIntegerAttribute(tree, 6207cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden REQ_NAVIGATION_ATTR, NULL, 0); 6216507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden int32_t reqFiveWayNav = getIntegerAttribute(tree, 6227cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden REQ_FIVE_WAY_NAV_ATTR, NULL, 0); 6237cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf("uses-configuation:"); 6247cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (reqTouchScreen != 0) { 6257cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf(" reqTouchScreen='%d'", reqTouchScreen); 6267cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 6277cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (reqKeyboardType != 0) { 6287cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf(" reqKeyboardType='%d'", reqKeyboardType); 6297cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 6307cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (reqHardKeyboard != 0) { 6317cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf(" reqHardKeyboard='%d'", reqHardKeyboard); 6327cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 6337cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (reqNavigation != 0) { 6347cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf(" reqNavigation='%d'", reqNavigation); 6357cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 6367cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (reqFiveWayNav != 0) { 6377cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf(" reqFiveWayNav='%d'", reqFiveWayNav); 6387cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 6397cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden printf("\n"); 6407cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } else if (tag == "supports-density") { 6417cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int32_t dens = getIntegerAttribute(tree, DENSITY_ATTR, &error); 6425778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 6435778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:density' attribute: %s\n", 6445778822d86b0337407514b9372562b86edfa91cdAndreas Huber error.string()); 6455778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 6465778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6475778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("supports-density:'%d'\n", dens); 6485778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (tag == "supports-screens") { 6495778822d86b0337407514b9372562b86edfa91cdAndreas Huber smallScreen = getIntegerAttribute(tree, 6505778822d86b0337407514b9372562b86edfa91cdAndreas Huber SMALL_SCREEN_ATTR, NULL, 1); 6515778822d86b0337407514b9372562b86edfa91cdAndreas Huber normalScreen = getIntegerAttribute(tree, 6525778822d86b0337407514b9372562b86edfa91cdAndreas Huber NORMAL_SCREEN_ATTR, NULL, 1); 6535778822d86b0337407514b9372562b86edfa91cdAndreas Huber largeScreen = getIntegerAttribute(tree, 6545778822d86b0337407514b9372562b86edfa91cdAndreas Huber LARGE_SCREEN_ATTR, NULL, 1); 6555778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6565778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (depth == 3 && withinApplication) { 657eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber withinActivity = false; 658eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber withinReceiver = false; 659eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber if(tag == "activity") { 660eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber withinActivity = true; 661eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber activityName = getAttribute(tree, NAME_ATTR, &error); 6625778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 663eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string()); 6645778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 665eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber } 6665778822d86b0337407514b9372562b86edfa91cdAndreas Huber 667eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); 6685778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 669eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string()); 6705778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 6711bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 672ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 673ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); 674ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (error != "") { 675ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); 6765778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 6775778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6785778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (tag == "uses-library") { 6795778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 libraryName = getAttribute(tree, NAME_ATTR, &error); 6805778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 6815778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:name' attribute for uses-library: %s\n", error.string()); 6825778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 6835778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6845778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("uses-library:'%s'\n", libraryName.string()); 6855778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (tag == "receiver") { 6865778822d86b0337407514b9372562b86edfa91cdAndreas Huber withinReceiver = true; 6875778822d86b0337407514b9372562b86edfa91cdAndreas Huber receiverName = getAttribute(tree, NAME_ATTR, &error); 688575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 6895778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 6905778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:name' attribute for receiver: %s\n", error.string()); 6915778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 6925778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6935778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6945778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (depth == 5) { 6955778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (withinActivity) { 6965778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tag == "action") { 6975778822d86b0337407514b9372562b86edfa91cdAndreas Huber //printf("LOG: action tag\n"); 6985778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 action = getAttribute(tree, NAME_ATTR, &error); 6995778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 7005778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string()); 7015778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 7025778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7035778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (action == "android.intent.action.MAIN") { 7045778822d86b0337407514b9372562b86edfa91cdAndreas Huber isMainActivity = true; 7055778822d86b0337407514b9372562b86edfa91cdAndreas Huber //printf("LOG: isMainActivity==true\n"); 7065778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7075778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (tag == "category") { 7085778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 category = getAttribute(tree, NAME_ATTR, &error); 7095778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 7105778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'name' attribute: %s\n", error.string()); 7115778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 7125778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7135778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (category == "android.intent.category.LAUNCHER") { 7145778822d86b0337407514b9372562b86edfa91cdAndreas Huber isLauncherActivity = true; 7155778822d86b0337407514b9372562b86edfa91cdAndreas Huber //printf("LOG: isLauncherActivity==true\n"); 7165778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7175778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7185778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (withinReceiver) { 7195778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tag == "action") { 7205778822d86b0337407514b9372562b86edfa91cdAndreas Huber String8 action = getAttribute(tree, NAME_ATTR, &error); 7215778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (error != "") { 7225778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR getting 'android:name' attribute for receiver: %s\n", error.string()); 7235778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 7245778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7255778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (action == "android.appwidget.action.APPWIDGET_UPDATE") { 7265778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char *rName = getComponentName(pkg, receiverName); 727575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (rName != NULL) { 7285778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("gadget-receiver:'%s/%s'\n", pkg.string(), rName); 7295778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7305778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7315778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7325778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7335778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7345778822d86b0337407514b9372562b86edfa91cdAndreas Huber 735c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (depth < 2) { 736c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber withinApplication = false; 737c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 7385778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (depth < 3) { 7395778822d86b0337407514b9372562b86edfa91cdAndreas Huber //if (withinActivity) printf("LOG: withinActivity==false\n"); 7405778822d86b0337407514b9372562b86edfa91cdAndreas Huber withinActivity = false; 7415778822d86b0337407514b9372562b86edfa91cdAndreas Huber withinReceiver = false; 7428ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 7438ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 7448ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (depth < 5) { 7458ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber //if (isMainActivity) printf("LOG: isMainActivity==false\n"); 7468ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber //if (isLauncherActivity) printf("LOG: isLauncherActivity==false\n"); 7478ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber isMainActivity = false; 7488ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber isLauncherActivity = false; 7498ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 7508ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 7518ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (withinActivity && isMainActivity && isLauncherActivity) { 7528ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber printf("launchable activity:"); 7538ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber const char *aName = getComponentName(pkg, activityName); 7548ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (aName != NULL) { 7558ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber printf(" name='%s'", aName); 7568ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 7578ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber printf("label='%s' icon='%s'\n", 7588ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber activityLabel.string(), 759575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber activityIcon.string()); 760575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber } 7618ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 7628ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 7638ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber // Determine default values for any unspecified screen sizes, 7648ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber // based on the target SDK of the package. As of 4 (donut) 7658ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber // the screen size support was introduced, so all default to 7665778822d86b0337407514b9372562b86edfa91cdAndreas Huber // enabled. 7675778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (smallScreen > 0) { 7685778822d86b0337407514b9372562b86edfa91cdAndreas Huber smallScreen = targetSdk >= 4 ? -1 : 0; 7695778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7705778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (normalScreen > 0) { 7715778822d86b0337407514b9372562b86edfa91cdAndreas Huber normalScreen = -1; 772575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber } 773575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (largeScreen > 0) { 7745778822d86b0337407514b9372562b86edfa91cdAndreas Huber largeScreen = targetSdk >= 4 ? -1 : 0; 7755778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7765778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("supports-screens:"); 7775778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (smallScreen != 0) printf(" 'small'"); 7785778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (normalScreen != 0) printf(" 'normal'"); 7795778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (largeScreen != 0) printf(" 'large'"); 7805778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("\n"); 7815778822d86b0337407514b9372562b86edfa91cdAndreas Huber 782c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber printf("locales:"); 783c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber Vector<String8> locales; 784c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber res.getLocales(&locales); 7855778822d86b0337407514b9372562b86edfa91cdAndreas Huber const size_t NL = locales.size(); 7865778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i=0; i<NL; i++) { 7875778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* localeStr = locales[i].string(); 7885778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (localeStr == NULL || strlen(localeStr) == 0) { 7892d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber localeStr = "--_--"; 7902d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber } 7915778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf(" '%s'", localeStr); 7925778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7935778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("\n"); 7945778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7955778822d86b0337407514b9372562b86edfa91cdAndreas Huber Vector<ResTable_config> configs; 7965778822d86b0337407514b9372562b86edfa91cdAndreas Huber res.getConfigurations(&configs); 7975778822d86b0337407514b9372562b86edfa91cdAndreas Huber SortedVector<int> densities; 7985778822d86b0337407514b9372562b86edfa91cdAndreas Huber const size_t NC = configs.size(); 7995778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i=0; i<NC; i++) { 8005778822d86b0337407514b9372562b86edfa91cdAndreas Huber int dens = configs[i].density; 8015778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (dens == 0) dens = 160; 8025778822d86b0337407514b9372562b86edfa91cdAndreas Huber densities.add(dens); 803575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber } 804575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 8055778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("densities:"); 806575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber const size_t ND = densities.size(); 8075778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i=0; i<ND; i++) { 8085778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf(" '%d'", densities[i]); 8095778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8105778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("\n"); 8115778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8125778822d86b0337407514b9372562b86edfa91cdAndreas Huber AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); 8135778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (dir != NULL) { 8145778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (dir->getFileCount() > 0) { 8155778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("native-code:"); 8165778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i=0; i<dir->getFileCount(); i++) { 8175778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf(" '%s'", dir->getFileName(i).string()); 8185778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 819c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber printf("\n"); 820c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 821c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber delete dir; 822c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 823c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } else if (strcmp("configurations", option) == 0) { 824c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber Vector<ResTable_config> configs; 8255778822d86b0337407514b9372562b86edfa91cdAndreas Huber res.getConfigurations(&configs); 8265778822d86b0337407514b9372562b86edfa91cdAndreas Huber const size_t N = configs.size(); 8275778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i=0; i<N; i++) { 8285778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf("%s\n", configs[i].toString().string()); 8295778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8305778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 8315778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); 8325778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 8335778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8345778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8355778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8365778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = NO_ERROR; 8375778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8385778822d86b0337407514b9372562b86edfa91cdAndreas Huberbail: 8395778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (asset) { 8405778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete asset; 8415778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8425778822d86b0337407514b9372562b86edfa91cdAndreas Huber return (result != NO_ERROR); 8435778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 8445778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8455778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8465778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 8475778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Handle the "add" command, which wants to add files to a new or 8485778822d86b0337407514b9372562b86edfa91cdAndreas Huber * pre-existing archive. 8495778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 8505778822d86b0337407514b9372562b86edfa91cdAndreas Huberint doAdd(Bundle* bundle) 8515778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 8525778822d86b0337407514b9372562b86edfa91cdAndreas Huber ZipFile* zip = NULL; 8535778822d86b0337407514b9372562b86edfa91cdAndreas Huber status_t result = UNKNOWN_ERROR; 8545778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* zipFileName; 8555778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8565778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getUpdate()) { 8575778822d86b0337407514b9372562b86edfa91cdAndreas Huber /* avoid confusion */ 8585778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: can't use '-u' with add\n"); 8595778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 8605778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8615778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8625778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (bundle->getFileSpecCount() < 1) { 8635778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: must specify zip file name\n"); 8645778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 8655778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8665778822d86b0337407514b9372562b86edfa91cdAndreas Huber zipFileName = bundle->getFileSpecEntry(0); 8675778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8680db280176bd3277e3256252d063f3712b1905ba9Andreas Huber if (bundle->getFileSpecCount() < 2) { 8690db280176bd3277e3256252d063f3712b1905ba9Andreas Huber fprintf(stderr, "NOTE: nothing to do\n"); 8705778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 8715778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8725778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8735778822d86b0337407514b9372562b86edfa91cdAndreas Huber zip = openReadWrite(zipFileName, true); 8745778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (zip == NULL) { 8755778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); 8765778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 8775778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8785778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8795778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (int i = 1; i < bundle->getFileSpecCount(); i++) { 8805778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* fileName = bundle->getFileSpecEntry(i); 8815778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8825778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { 8835778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf(" '%s'... (from gzip)\n", fileName); 8845778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); 8855778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 8865778822d86b0337407514b9372562b86edfa91cdAndreas Huber printf(" '%s'...\n", fileName); 8875778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = zip->add(fileName, bundle->getCompressionMethod(), NULL); 8885778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8895778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (result != NO_ERROR) { 8905778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); 8915778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (result == NAME_NOT_FOUND) 8925778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, ": file not found\n"); 8935778822d86b0337407514b9372562b86edfa91cdAndreas Huber else if (result == ALREADY_EXISTS) 8945778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, ": already exists in archive\n"); 8955778822d86b0337407514b9372562b86edfa91cdAndreas Huber else 8965778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "\n"); 8975778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 8985778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8995778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9005778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9015778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = NO_ERROR; 9025778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9035778822d86b0337407514b9372562b86edfa91cdAndreas Huberbail: 9045778822d86b0337407514b9372562b86edfa91cdAndreas Huber delete zip; 9055778822d86b0337407514b9372562b86edfa91cdAndreas Huber return (result != NO_ERROR); 9065778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 9075778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9085778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9091bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber/* 9107541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber * Delete files from an existing archive. 9117541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber */ 9127541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huberint doRemove(Bundle* bundle) 9137541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber{ 9147541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber ZipFile* zip = NULL; 9157541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber status_t result = UNKNOWN_ERROR; 9167541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber const char* zipFileName; 9177541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber 9187541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (bundle->getFileSpecCount() < 1) { 9197541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber fprintf(stderr, "ERROR: must specify zip file name\n"); 9201bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber goto bail; 9211bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 9227541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber zipFileName = bundle->getFileSpecEntry(0); 9231bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 9241bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber if (bundle->getFileSpecCount() < 2) { 9257541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber fprintf(stderr, "NOTE: nothing to do\n"); 9267541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber goto bail; 9277541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 9281bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 9291bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber zip = openReadWrite(zipFileName, false); 9301bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber if (zip == NULL) { 9315778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", 9325778822d86b0337407514b9372562b86edfa91cdAndreas Huber zipFileName); 9331bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber goto bail; 9341bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 9355778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9365778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (int i = 1; i < bundle->getFileSpecCount(); i++) { 9375778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* fileName = bundle->getFileSpecEntry(i); 9385778822d86b0337407514b9372562b86edfa91cdAndreas Huber ZipEntry* entry; 9395778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9405778822d86b0337407514b9372562b86edfa91cdAndreas Huber entry = zip->getEntryByName(fileName); 9415778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (entry == NULL) { 9428ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber printf(" '%s' NOT FOUND\n", fileName); 9438ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber continue; 9445778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9455778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9465778822d86b0337407514b9372562b86edfa91cdAndreas Huber result = zip->remove(entry); 9475778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9487cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (result != NO_ERROR) { 9497cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden fprintf(stderr, "Unable to delete '%s' from '%s'\n", 9507cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden bundle->getFileSpecEntry(i), zipFileName); 9517cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden goto bail; 9527cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 9537cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 9547cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 9557cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden /* update the archive */ 9567cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden zip->flush(); 9577cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 9587cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenbail: 9597cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden delete zip; 9607cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden return (result != NO_ERROR); 9617cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden} 9627cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 9637cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 9647cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden/* 9657cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * Package up an asset directory and associated application files. 9667cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden */ 9675778822d86b0337407514b9372562b86edfa91cdAndreas Huberint doPackage(Bundle* bundle) 9685778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 9695778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* outputAPKFile; 9705778822d86b0337407514b9372562b86edfa91cdAndreas Huber int retVal = 1; 9715778822d86b0337407514b9372562b86edfa91cdAndreas Huber status_t err; 9725778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<AaptAssets> assets; 9735778822d86b0337407514b9372562b86edfa91cdAndreas Huber int N; 9745778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9755778822d86b0337407514b9372562b86edfa91cdAndreas Huber // -c zz_ZZ means do pseudolocalization 9765778822d86b0337407514b9372562b86edfa91cdAndreas Huber ResourceFilter filter; 9775778822d86b0337407514b9372562b86edfa91cdAndreas Huber err = filter.parse(bundle->getConfigurations()); 9785778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (err != NO_ERROR) { 9795778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 9805778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9815778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (filter.containsPseudo()) { 9825778822d86b0337407514b9372562b86edfa91cdAndreas Huber bundle->setPseudolocalize(true); 9835778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9845778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9855778822d86b0337407514b9372562b86edfa91cdAndreas Huber N = bundle->getFileSpecCount(); 9865778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 9875778822d86b0337407514b9372562b86edfa91cdAndreas Huber && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDir() == NULL) { 9885778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: no input files\n"); 9895778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 9905778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9915778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9925778822d86b0337407514b9372562b86edfa91cdAndreas Huber outputAPKFile = bundle->getOutputAPKFile(); 9935778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9945778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Make sure the filenames provided exist and are of the appropriate type. 9955778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (outputAPKFile) { 9965778822d86b0337407514b9372562b86edfa91cdAndreas Huber FileType type; 9975778822d86b0337407514b9372562b86edfa91cdAndreas Huber type = getFileType(outputAPKFile); 9985778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (type != kFileTypeNonexistent && type != kFileTypeRegular) { 9995778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, 10005778822d86b0337407514b9372562b86edfa91cdAndreas Huber "ERROR: output file '%s' exists but is not regular file\n", 10015778822d86b0337407514b9372562b86edfa91cdAndreas Huber outputAPKFile); 10025778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 10035778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1004c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 1005c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1006c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // Load the assets. 1007c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber assets = new AaptAssets(); 1008c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber err = assets->slurpFromArgs(bundle); 1009c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (err < 0) { 1010c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber goto bail; 1011c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 1012c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1013c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (bundle->getVerbose()) { 1014c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber assets->print(); 1015c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 1016c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1017c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // If they asked for any files that need to be compiled, do so. 1018c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { 1019c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber err = buildResources(bundle, assets); 1020c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (err != 0) { 1021c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber goto bail; 1022c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 1023c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 1024c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1025c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // At this point we've read everything and processed everything. From here 10265778822d86b0337407514b9372562b86edfa91cdAndreas Huber // on out it's just writing output files. 10275778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (SourcePos::hasErrors()) { 10285778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 10295778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10305778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10315778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Write out R.java constants 10325778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (assets->getPackage() == assets->getSymbolsPrivatePackage()) { 10335778822d86b0337407514b9372562b86edfa91cdAndreas Huber err = writeResourceSymbols(bundle, assets, assets->getPackage(), true); 10345778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (err < 0) { 10355778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 10366507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden } 10376507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden } else { 10386507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden err = writeResourceSymbols(bundle, assets, assets->getPackage(), false); 10396507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden if (err < 0) { 10406507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden goto bail; 10416507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden } 10426507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true); 10436507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden if (err < 0) { 10445778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 10455778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10465778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10475778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10485778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Write the apk 10495778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (outputAPKFile) { 10505778822d86b0337407514b9372562b86edfa91cdAndreas Huber err = writeAPK(bundle, assets, String8(outputAPKFile)); 10515778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (err != NO_ERROR) { 10525778822d86b0337407514b9372562b86edfa91cdAndreas Huber fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputAPKFile); 10535778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto bail; 10545778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10555778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10565778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10575778822d86b0337407514b9372562b86edfa91cdAndreas Huber retVal = 0; 10585778822d86b0337407514b9372562b86edfa91cdAndreas Huberbail: 10595778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (SourcePos::hasErrors()) { 10605778822d86b0337407514b9372562b86edfa91cdAndreas Huber SourcePos::printErrors(stderr); 10615778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10625778822d86b0337407514b9372562b86edfa91cdAndreas Huber return retVal; 10635778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 10645778822d86b0337407514b9372562b86edfa91cdAndreas Huber