diff options
-rw-r--r-- | tools/aapt/AaptAssets.cpp | 1 | ||||
-rw-r--r-- | tools/aapt/Command.cpp | 13 | ||||
-rw-r--r-- | tools/aapt/Resource.cpp | 7 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.cpp | 78 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.h | 7 |
5 files changed, 99 insertions, 7 deletions
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index 3c3edda85e4f..13ae24b7d29e 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -964,7 +964,6 @@ void AaptAssets::addResource(const String8& leafName, const String8& path, subdir->addFile(leafName, grr); } - ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) { int count; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 15648bdd1b3b..fdcc7aa03775 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -2501,14 +2501,21 @@ static status_t addResourcesToBuilder(const sp<AaptDir>& dir, const sp<ApkBuilde const size_t numConfigs = gp->getFiles().size(); for (size_t j = 0; j < numConfigs; j++) { status_t err = NO_ERROR; + const sp<AaptFile>& file = gp->getFiles().valueAt(j); + if (!file->hasData()) { + // Empty files do not get written. + continue; + } + if (ignoreConfig) { - err = builder->getBaseSplit()->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); + err = builder->getBaseSplit()->addEntry(gp->getPath(), file); } else { - err = builder->addEntry(gp->getPath(), gp->getFiles().valueAt(j)); + err = builder->addEntry(gp->getPath(), file); } + if (err != NO_ERROR) { fprintf(stderr, "Failed to add %s (%s) to builder.\n", - gp->getPath().string(), gp->getFiles()[j]->getPrintableSource().string()); + gp->getPath().string(), file->getPrintableSource().string()); return err; } } diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 3330b1a78c1e..2bf52066b618 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -1403,7 +1403,8 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil String8 src = it.getFile()->getPrintableSource(); err = compileXmlFile(bundle, assets, String16(it.getBaseName()), it.getFile(), &table, xmlFlags); - if (err == NO_ERROR) { + // Only verify IDs if there was no error and the file is non-empty. + if (err == NO_ERROR && it.getFile()->hasData()) { ResXMLTree block; block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true); checkForIds(src, block); @@ -1550,7 +1551,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil String8 src = it.getFile()->getPrintableSource(); err = compileXmlFile(bundle, assets, String16(it.getBaseName()), it.getFile(), &table, xmlFlags); - if (err == NO_ERROR) { + if (err == NO_ERROR && it.getFile()->hasData()) { ResXMLTree block; block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true); checkForIds(src, block); @@ -1598,7 +1599,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.xmlRoot, workItem.file, &table, xmlCompilationFlags); - if (err == NO_ERROR) { + if (err == NO_ERROR && workItem.file->hasData()) { assets->addResource(workItem.resPath.getPathLeaf(), workItem.resPath, workItem.file, diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 60f0d56e09bf..619ae6228318 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -78,6 +78,13 @@ status_t compileXmlFile(const Bundle* bundle, ResourceTable* table, int options) { + if (table->versionForCompat(bundle, resourceName, target, root)) { + // The file was versioned, so stop processing here. + // The resource entry has already been removed and the new one added. + // The `target` file will be empty, but empty files do not get written to the APK. + return NO_ERROR; + } + if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) { root->removeWhitespace(true, NULL); } else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) { @@ -4758,6 +4765,77 @@ static bool IsTransitionElement(const String16& name) { return false; } +bool ResourceTable::versionForCompat(const Bundle* bundle, const String16& resourceName, + const sp<AaptFile>& target, const sp<XMLNode>& root) { + XMLNode* node = root.get(); + while (node->getType() != XMLNode::TYPE_ELEMENT) { + // We're assuming the root element is what we're looking for, which can only be under a + // bunch of namespace declarations. + if (node->getChildren().size() != 1) { + // Not sure what to do, bail. + return false; + } + node = node->getChildren().itemAt(0).get(); + } + + if (node->getElementNamespace().size() != 0) { + // Not something we care about. + return false; + } + + int versionedSdk = 0; + if (node->getElementName() == String16("adaptive-icon")) { + versionedSdk = SDK_O; + } + + const int minSdkVersion = getMinSdkVersion(bundle); + const ConfigDescription config(target->getGroupEntry().toParams()); + if (versionedSdk <= minSdkVersion || versionedSdk <= config.sdkVersion) { + return false; + } + + sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()), + String16(target->getResourceType()), resourceName); + if (!shouldGenerateVersionedResource(cl, config, versionedSdk)) { + return false; + } + + // Remove the original entry. + cl->removeEntry(config); + + // We need to wholesale version this file. + ConfigDescription newConfig(config); + newConfig.sdkVersion = versionedSdk; + sp<AaptFile> newFile = new AaptFile(target->getSourceFile(), + AaptGroupEntry(newConfig), target->getResourceType()); + String8 resPath = String8::format("res/%s/%s.xml", + newFile->getGroupEntry().toDirName(target->getResourceType()).string(), + String8(resourceName).string()); + resPath.convertToResPath(); + + // Add a resource table entry. + addEntry(SourcePos(), + String16(mAssets->getPackage()), + String16(target->getResourceType()), + resourceName, + String16(resPath), + NULL, + &newConfig); + + // Schedule this to be compiled. + CompileResourceWorkItem item; + item.resourceName = resourceName; + item.resPath = resPath; + item.file = newFile; + item.xmlRoot = root->clone(); + item.needsCompiling = false; // This step occurs after we parse/assign, so we don't need + // to do it again. + mWorkQueue.push(item); + + // Now mark the old entry as deleted. + return true; +} + status_t ResourceTable::modifyForCompat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index cf1e992ec330..aff22d4d1364 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -203,6 +203,9 @@ public: size_t numLocalResources() const; bool hasResources() const; + bool versionForCompat(const Bundle* bundle, const String16& resourceName, + const sp<AaptFile>& file, const sp<XMLNode>& root); + status_t modifyForCompat(const Bundle* bundle); status_t modifyForCompat(const Bundle* bundle, const String16& resourceName, @@ -431,6 +434,10 @@ public: mEntries.add(config, entry); } + void removeEntry(const ResTable_config& config) { + mEntries.removeItem(config); + } + const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; } private: const String16 mName; |