diff options
author | Adam Lesinski <adamlesinski@google.com> | 2015-05-14 17:58:14 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2015-05-14 20:56:10 -0700 |
commit | 39c353a6caada777348c14f6dc9abee2d4d9a3be (patch) | |
tree | 697823578d99994617ab8cea0fa002d8b5e5bcbf /tools | |
parent | b731c3d944ccf46b7d0115f63b63eee5ab8abf1a (diff) | |
download | frameworks_base-39c353a6caada777348c14f6dc9abee2d4d9a3be.zip frameworks_base-39c353a6caada777348c14f6dc9abee2d4d9a3be.tar.gz frameworks_base-39c353a6caada777348c14f6dc9abee2d4d9a3be.tar.bz2 |
AAPT2: Fix layout versioning
Change-Id: I37190cf8a1f0a81c068aeb2b5326b3b3080f75a5
Diffstat (limited to 'tools')
-rw-r--r-- | tools/aapt2/Main.cpp | 70 | ||||
-rw-r--r-- | tools/aapt2/data/Makefile | 2 |
2 files changed, 58 insertions, 14 deletions
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index 025ede5..91639c5 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -189,16 +189,16 @@ void versionStylesForCompat(const std::shared_ptr<ResourceTable>& table) { } struct CompileItem { - Source source; ResourceName name; ConfigDescription config; + Source source; std::string extension; }; struct LinkItem { - Source source; ResourceName name; ConfigDescription config; + Source source; std::string originalPath; ZipFile* apk; std::u16string originalPackage; @@ -236,7 +236,8 @@ std::string buildFileReference(const LinkItem& item) { return buildFileReference(item.name, item.config, getExtension<char>(item.originalPath)); } -bool addFileReference(const std::shared_ptr<ResourceTable>& table, const CompileItem& item) { +template <typename T> +bool addFileReference(const std::shared_ptr<ResourceTable>& table, const T& item) { StringPool& pool = table->getValueStringPool(); StringPool::Ref ref = pool.makeRef(util::utf8ToUtf16(buildFileReference(item)), StringPool::Context{ 0, item.config }); @@ -334,9 +335,40 @@ bool compileXml(const AaptOptions& options, const std::shared_ptr<ResourceTable> return true; } -bool linkXml(const AaptOptions& options, const std::shared_ptr<IResolver>& resolver, - const LinkItem& item, const void* data, size_t dataLen, ZipFile* outApk, - std::queue<LinkItem>* outQueue) { +/** + * Determines if a layout should be auto generated based on SDK level. We do not + * generate a layout if there is already a layout defined whose SDK version is greater than + * the one we want to generate. + */ +bool shouldGenerateVersionedResource(const std::shared_ptr<const ResourceTable>& table, + const ResourceName& name, const ConfigDescription& config, + int sdkVersionToGenerate) { + assert(sdkVersionToGenerate > config.sdkVersion); + const ResourceTableType* type; + const ResourceEntry* entry; + std::tie(type, entry) = table->findResource(name); + assert(type && entry); + + auto iter = std::lower_bound(entry->values.begin(), entry->values.end(), config, + [](const ResourceConfigValue& lhs, const ConfigDescription& config) -> bool { + return lhs.config < config; + }); + + assert(iter != entry->values.end()); + ++iter; + + if (iter == entry->values.end()) { + return true; + } + + ConfigDescription newConfig = config; + newConfig.sdkVersion = sdkVersionToGenerate; + return newConfig < iter->config; +} + +bool linkXml(const AaptOptions& options, const std::shared_ptr<ResourceTable>& table, + const std::shared_ptr<IResolver>& resolver, const LinkItem& item, + const void* data, size_t dataLen, ZipFile* outApk, std::queue<LinkItem>* outQueue) { std::shared_ptr<android::ResXMLTree> tree = std::make_shared<android::ResXMLTree>(); if (tree->setTo(data, dataLen, false) != android::NO_ERROR) { return false; @@ -376,9 +408,21 @@ bool linkXml(const AaptOptions& options, const std::shared_ptr<IResolver>& resol if (minStrippedSdk.value() > 0) { // Something was stripped, so let's generate a new file // with the version of the smallest SDK version stripped. - LinkItem newWork = item; - newWork.config.sdkVersion = minStrippedSdk.value(); - outQueue->push(newWork); + // We can only generate a versioned layout if there doesn't exist a layout + // with sdk version greater than the current one but less than the one we + // want to generate. + if (shouldGenerateVersionedResource(table, item.name, item.config, + minStrippedSdk.value())) { + LinkItem newWork = item; + newWork.config.sdkVersion = minStrippedSdk.value(); + outQueue->push(newWork); + + if (!addFileReference(table, newWork)) { + Logger::error(options.output) << "failed to add auto-versioned resource '" + << newWork.name << "'." << std::endl; + return false; + } + } } if (outApk->add(outBuffer, buildFileReference(item).data(), ZipEntry::kCompressDeflated, @@ -604,7 +648,7 @@ static void addApkFilesToLinkQueue(const std::u16string& package, const Source& newSource.path += "/"; newSource.path += pathUtf8; outLinkQueue->push(LinkItem{ - newSource, name, value.config, pathUtf8, apk.get(), + name, value.config, newSource, pathUtf8, apk.get(), table->getPackage() }); // Now rewrite the file path. if (mangle) { @@ -743,8 +787,8 @@ bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outT void* uncompressedData = item.apk->uncompress(entry); assert(uncompressedData); - if (!linkXml(options, resolver, item, uncompressedData, entry->getUncompressedLen(), - &outApk, &linkQueue)) { + if (!linkXml(options, outTable, resolver, item, uncompressedData, + entry->getUncompressedLen(), &outApk, &linkQueue)) { Logger::error(options.output) << "failed to link '" << item.originalPath << "'." << std::endl; return false; @@ -862,9 +906,9 @@ bool compile(const AaptOptions& options, const std::shared_ptr<ResourceTable>& t } compileQueue.push(CompileItem{ - source, ResourceName{ table->getPackage(), *type, pathData.name }, pathData.config, + source, pathData.extension }); } diff --git a/tools/aapt2/data/Makefile b/tools/aapt2/data/Makefile index 6b5fafa..ce5201b 100644 --- a/tools/aapt2/data/Makefile +++ b/tools/aapt2/data/Makefile @@ -49,7 +49,7 @@ $(info PRIVATE_INTERMEDIATE_TABLES = $(PRIVATE_INTERMEDIATE_TABLES)) # returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml define make-collect-rule $(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES)) - $(AAPT) compile --package $(LOCAL_PACKAGE) --binding $(LOCAL_GEN) -o $$@ $$^ + $(AAPT) compile --package $(LOCAL_PACKAGE) -o $$@ $$^ endef # Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml |