diff options
Diffstat (limited to 'tools/aapt/Package.cpp')
-rw-r--r-- | tools/aapt/Package.cpp | 505 |
1 files changed, 0 insertions, 505 deletions
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp deleted file mode 100644 index 872d95c509f7..000000000000 --- a/tools/aapt/Package.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Package assets into Zip files. -// -#include "Main.h" -#include "AaptAssets.h" -#include "ResourceTable.h" -#include "ResourceFilter.h" - -#include <androidfw/misc.h> - -#include <utils/Log.h> -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> -#include <utils/misc.h> - -#include <sys/types.h> -#include <dirent.h> -#include <ctype.h> -#include <errno.h> - -using namespace android; - -static const char* kExcludeExtension = ".EXCLUDE"; - -/* these formats are already compressed, or don't compress well */ -static const char* kNoCompressExt[] = { - ".jpg", ".jpeg", ".png", ".gif", - ".wav", ".mp2", ".mp3", ".ogg", ".aac", - ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", - ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", - ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", - ".amr", ".awb", ".wma", ".wmv" -}; - -/* fwd decls, so I can write this downward */ -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptAssets>& assets); -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptDir>& dir, - const AaptGroupEntry& ge, const ResourceFilter* filter); -bool processFile(Bundle* bundle, ZipFile* zip, - const sp<AaptGroup>& group, const sp<AaptFile>& file); -bool okayToCompress(Bundle* bundle, const String8& pathName); -ssize_t processJarFiles(Bundle* bundle, ZipFile* zip); - -/* - * The directory hierarchy looks like this: - * "outputDir" and "assetRoot" are existing directories. - * - * On success, "bundle->numPackages" will be the number of Zip packages - * we created. - */ -status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets, - const String8& outputFile) -{ - #if BENCHMARK - fprintf(stdout, "BENCHMARK: Starting APK Bundling \n"); - long startAPKTime = clock(); - #endif /* BENCHMARK */ - - status_t result = NO_ERROR; - ZipFile* zip = NULL; - int count; - - //bundle->setPackageCount(0); - - /* - * Prep the Zip archive. - * - * If the file already exists, fail unless "update" or "force" is set. - * If "update" is set, update the contents of the existing archive. - * Else, if "force" is set, remove the existing archive. - */ - FileType fileType = getFileType(outputFile.string()); - if (fileType == kFileTypeNonexistent) { - // okay, create it below - } else if (fileType == kFileTypeRegular) { - if (bundle->getUpdate()) { - // okay, open it below - } else if (bundle->getForce()) { - if (unlink(outputFile.string()) != 0) { - fprintf(stderr, "ERROR: unable to remove '%s': %s\n", outputFile.string(), - strerror(errno)); - goto bail; - } - } else { - fprintf(stderr, "ERROR: '%s' exists (use '-f' to force overwrite)\n", - outputFile.string()); - goto bail; - } - } else { - fprintf(stderr, "ERROR: '%s' exists and is not a regular file\n", outputFile.string()); - goto bail; - } - - if (bundle->getVerbose()) { - printf("%s '%s'\n", (fileType == kFileTypeNonexistent) ? "Creating" : "Opening", - outputFile.string()); - } - - status_t status; - zip = new ZipFile; - status = zip->open(outputFile.string(), ZipFile::kOpenReadWrite | ZipFile::kOpenCreate); - if (status != NO_ERROR) { - fprintf(stderr, "ERROR: unable to open '%s' as Zip file for writing\n", - outputFile.string()); - goto bail; - } - - if (bundle->getVerbose()) { - printf("Writing all files...\n"); - } - - count = processAssets(bundle, zip, assets); - if (count < 0) { - fprintf(stderr, "ERROR: unable to process assets while packaging '%s'\n", - outputFile.string()); - result = count; - goto bail; - } - - if (bundle->getVerbose()) { - printf("Generated %d file%s\n", count, (count==1) ? "" : "s"); - } - - count = processJarFiles(bundle, zip); - if (count < 0) { - fprintf(stderr, "ERROR: unable to process jar files while packaging '%s'\n", - outputFile.string()); - result = count; - goto bail; - } - - if (bundle->getVerbose()) - printf("Included %d file%s from jar/zip files.\n", count, (count==1) ? "" : "s"); - - result = NO_ERROR; - - /* - * Check for cruft. We set the "marked" flag on all entries we created - * or decided not to update. If the entry isn't already slated for - * deletion, remove it now. - */ - { - if (bundle->getVerbose()) - printf("Checking for deleted files\n"); - int i, removed = 0; - for (i = 0; i < zip->getNumEntries(); i++) { - ZipEntry* entry = zip->getEntryByIndex(i); - - if (!entry->getMarked() && entry->getDeleted()) { - if (bundle->getVerbose()) { - printf(" (removing crufty '%s')\n", - entry->getFileName()); - } - zip->remove(entry); - removed++; - } - } - if (bundle->getVerbose() && removed > 0) - printf("Removed %d file%s\n", removed, (removed==1) ? "" : "s"); - } - - /* tell Zip lib to process deletions and other pending changes */ - result = zip->flush(); - if (result != NO_ERROR) { - fprintf(stderr, "ERROR: Zip flush failed, archive may be hosed\n"); - goto bail; - } - - /* anything here? */ - if (zip->getNumEntries() == 0) { - if (bundle->getVerbose()) { - printf("Archive is empty -- removing %s\n", outputFile.getPathLeaf().string()); - } - delete zip; // close the file so we can remove it in Win32 - zip = NULL; - if (unlink(outputFile.string()) != 0) { - fprintf(stderr, "warning: could not unlink '%s'\n", outputFile.string()); - } - } - - // If we've been asked to generate a dependency file for the .ap_ package, - // do so here - if (bundle->getGenDependencies()) { - // The dependency file gets output to the same directory - // as the specified output file with an additional .d extension. - // e.g. bin/resources.ap_.d - String8 dependencyFile = outputFile; - dependencyFile.append(".d"); - - FILE* fp = fopen(dependencyFile.string(), "a"); - // Add this file to the dependency file - fprintf(fp, "%s \\\n", outputFile.string()); - fclose(fp); - } - - assert(result == NO_ERROR); - -bail: - delete zip; // must close before remove in Win32 - if (result != NO_ERROR) { - if (bundle->getVerbose()) { - printf("Removing %s due to earlier failures\n", outputFile.string()); - } - if (unlink(outputFile.string()) != 0) { - fprintf(stderr, "warning: could not unlink '%s'\n", outputFile.string()); - } - } - - if (result == NO_ERROR && bundle->getVerbose()) - printf("Done!\n"); - - #if BENCHMARK - fprintf(stdout, "BENCHMARK: End APK Bundling. Time Elapsed: %f ms \n",(clock() - startAPKTime)/1000.0); - #endif /* BENCHMARK */ - return result; -} - -ssize_t processAssets(Bundle* bundle, ZipFile* zip, - const sp<AaptAssets>& assets) -{ - ResourceFilter filter; - status_t status = filter.parse(bundle->getConfigurations()); - if (status != NO_ERROR) { - return -1; - } - - ssize_t count = 0; - - const size_t N = assets->getGroupEntries().size(); - for (size_t i=0; i<N; i++) { - const AaptGroupEntry& ge = assets->getGroupEntries()[i]; - - ssize_t res = processAssets(bundle, zip, assets, ge, &filter); - if (res < 0) { - return res; - } - - count += res; - } - - return count; -} - -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptDir>& dir, - const AaptGroupEntry& ge, const ResourceFilter* filter) -{ - ssize_t count = 0; - - const size_t ND = dir->getDirs().size(); - size_t i; - for (i=0; i<ND; i++) { - const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); - - const bool filterable = filter != NULL && subDir->getLeaf().find("mipmap-") != 0; - - if (filterable && subDir->getLeaf() != subDir->getPath() && !filter->match(ge.toParams())) { - continue; - } - - ssize_t res = processAssets(bundle, zip, subDir, ge, filterable ? filter : NULL); - if (res < 0) { - return res; - } - count += res; - } - - if (filter != NULL && !filter->match(ge.toParams())) { - return count; - } - - const size_t NF = dir->getFiles().size(); - for (i=0; i<NF; i++) { - sp<AaptGroup> gp = dir->getFiles().valueAt(i); - ssize_t fi = gp->getFiles().indexOfKey(ge); - if (fi >= 0) { - sp<AaptFile> fl = gp->getFiles().valueAt(fi); - if (!processFile(bundle, zip, gp, fl)) { - return UNKNOWN_ERROR; - } - count++; - } - } - - return count; -} - -/* - * Process a regular file, adding it to the archive if appropriate. - * - * If we're in "update" mode, and the file already exists in the archive, - * delete the existing entry before adding the new one. - */ -bool processFile(Bundle* bundle, ZipFile* zip, - const sp<AaptGroup>& group, const sp<AaptFile>& file) -{ - const bool hasData = file->hasData(); - - String8 storageName(group->getPath()); - storageName.convertToResPath(); - ZipEntry* entry; - bool fromGzip = false; - status_t result; - - /* - * See if the filename ends in ".EXCLUDE". We can't use - * String8::getPathExtension() because the length of what it considers - * to be an extension is capped. - * - * The Asset Manager doesn't check for ".EXCLUDE" in Zip archives, - * so there's no value in adding them (and it makes life easier on - * the AssetManager lib if we don't). - * - * NOTE: this restriction has been removed. If you're in this code, you - * should clean this up, but I'm in here getting rid of Path Name, and I - * don't want to make other potentially breaking changes --joeo - */ - int fileNameLen = storageName.length(); - int excludeExtensionLen = strlen(kExcludeExtension); - if (fileNameLen > excludeExtensionLen - && (0 == strcmp(storageName.string() + (fileNameLen - excludeExtensionLen), - kExcludeExtension))) { - fprintf(stderr, "warning: '%s' not added to Zip\n", storageName.string()); - return true; - } - - if (strcasecmp(storageName.getPathExtension().string(), ".gz") == 0) { - fromGzip = true; - storageName = storageName.getBasePath(); - } - - if (bundle->getUpdate()) { - entry = zip->getEntryByName(storageName.string()); - if (entry != NULL) { - /* file already exists in archive; there can be only one */ - if (entry->getMarked()) { - fprintf(stderr, - "ERROR: '%s' exists twice (check for with & w/o '.gz'?)\n", - file->getPrintableSource().string()); - return false; - } - if (!hasData) { - const String8& srcName = file->getSourceFile(); - time_t fileModWhen; - fileModWhen = getFileModDate(srcName.string()); - if (fileModWhen == (time_t) -1) { // file existence tested earlier, - return false; // not expecting an error here - } - - if (fileModWhen > entry->getModWhen()) { - // mark as deleted so add() will succeed - if (bundle->getVerbose()) { - printf(" (removing old '%s')\n", storageName.string()); - } - - zip->remove(entry); - } else { - // version in archive is newer - if (bundle->getVerbose()) { - printf(" (not updating '%s')\n", storageName.string()); - } - entry->setMarked(true); - return true; - } - } else { - // Generated files are always replaced. - zip->remove(entry); - } - } - } - - //android_setMinPriority(NULL, ANDROID_LOG_VERBOSE); - - if (fromGzip) { - result = zip->addGzip(file->getSourceFile().string(), storageName.string(), &entry); - } else if (!hasData) { - /* don't compress certain files, e.g. PNGs */ - int compressionMethod = bundle->getCompressionMethod(); - if (!okayToCompress(bundle, storageName)) { - compressionMethod = ZipEntry::kCompressStored; - } - result = zip->add(file->getSourceFile().string(), storageName.string(), compressionMethod, - &entry); - } else { - result = zip->add(file->getData(), file->getSize(), storageName.string(), - file->getCompressionMethod(), &entry); - } - if (result == NO_ERROR) { - if (bundle->getVerbose()) { - printf(" '%s'%s", storageName.string(), fromGzip ? " (from .gz)" : ""); - if (entry->getCompressionMethod() == ZipEntry::kCompressStored) { - printf(" (not compressed)\n"); - } else { - printf(" (compressed %d%%)\n", calcPercent(entry->getUncompressedLen(), - entry->getCompressedLen())); - } - } - entry->setMarked(true); - } else { - if (result == ALREADY_EXISTS) { - fprintf(stderr, " Unable to add '%s': file already in archive (try '-u'?)\n", - file->getPrintableSource().string()); - } else { - fprintf(stderr, " Unable to add '%s': Zip add failed\n", - file->getPrintableSource().string()); - } - return false; - } - - return true; -} - -/* - * Determine whether or not we want to try to compress this file based - * on the file extension. - */ -bool okayToCompress(Bundle* bundle, const String8& pathName) -{ - String8 ext = pathName.getPathExtension(); - int i; - - if (ext.length() == 0) - return true; - - for (i = 0; i < NELEM(kNoCompressExt); i++) { - if (strcasecmp(ext.string(), kNoCompressExt[i]) == 0) - return false; - } - - const android::Vector<const char*>& others(bundle->getNoCompressExtensions()); - for (i = 0; i < (int)others.size(); i++) { - const char* str = others[i]; - int pos = pathName.length() - strlen(str); - if (pos < 0) { - continue; - } - const char* path = pathName.string(); - if (strcasecmp(path + pos, str) == 0) { - return false; - } - } - - return true; -} - -bool endsWith(const char* haystack, const char* needle) -{ - size_t a = strlen(haystack); - size_t b = strlen(needle); - if (a < b) return false; - return strcasecmp(haystack+(a-b), needle) == 0; -} - -ssize_t processJarFile(ZipFile* jar, ZipFile* out) -{ - status_t err; - size_t N = jar->getNumEntries(); - size_t count = 0; - for (size_t i=0; i<N; i++) { - ZipEntry* entry = jar->getEntryByIndex(i); - const char* storageName = entry->getFileName(); - if (endsWith(storageName, ".class")) { - int compressionMethod = entry->getCompressionMethod(); - size_t size = entry->getUncompressedLen(); - const void* data = jar->uncompress(entry); - if (data == NULL) { - fprintf(stderr, "ERROR: unable to uncompress entry '%s'\n", - storageName); - return -1; - } - out->add(data, size, storageName, compressionMethod, NULL); - free((void*)data); - } - count++; - } - return count; -} - -ssize_t processJarFiles(Bundle* bundle, ZipFile* zip) -{ - status_t err; - ssize_t count = 0; - const android::Vector<const char*>& jars = bundle->getJarFiles(); - - size_t N = jars.size(); - for (size_t i=0; i<N; i++) { - ZipFile jar; - err = jar.open(jars[i], ZipFile::kOpenReadOnly); - if (err != 0) { - fprintf(stderr, "ERROR: unable to open '%s' as a zip file: %d\n", - jars[i], err); - return err; - } - err += processJarFile(&jar, zip); - if (err < 0) { - fprintf(stderr, "ERROR: unable to process '%s'\n", jars[i]); - return err; - } - count += err; - } - - return count; -} |