From 75f3a55cc569a9b61f540a85d9828e91bdca5047 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Wed, 3 Jun 2015 14:54:23 -0700 Subject: AAPT2: Change xml file parsing to DOM based We modify the XML of layouts and AndroidManifest enough that it warrants we operate on the tree in memory. These files are never very large so this should be fine. Change-Id: I5d597abdb3fca2a203cf7c0b40fcd926aecb3137 --- tools/aapt2/Main.cpp | 128 ++++++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 63 deletions(-) (limited to 'tools/aapt2/Main.cpp') diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index 91639c5b33a6..84957b4fbbd1 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -17,7 +17,6 @@ #include "AppInfo.h" #include "BigBuffer.h" #include "BinaryResourceParser.h" -#include "BinaryXmlPullParser.h" #include "BindingXmlPullParser.h" #include "Debug.h" #include "Files.h" @@ -128,7 +127,7 @@ void versionStylesForCompat(const std::shared_ptr& table) { auto iter = style.entries.begin(); while (iter != style.entries.end()) { if (iter->key.name.package == u"android") { - size_t sdkLevel = findAttributeSdkLevel(iter->key.name.entry); + size_t sdkLevel = findAttributeSdkLevel(iter->key.name); if (sdkLevel > 1 && sdkLevel > configValue.config.sdkVersion) { // Record that we are about to strip this. stripped.emplace_back(std::move(*iter)); @@ -300,6 +299,42 @@ struct AaptOptions { ResourceName dumpStyleTarget; }; +struct IdCollector : public xml::Visitor { + IdCollector(const Source& source, const std::shared_ptr& table) : + mSource(source), mTable(table) { + } + + virtual void visit(xml::Text* node) override {} + + virtual void visit(xml::Namespace* node) override { + for (const auto& child : node->children) { + child->accept(this); + } + } + + virtual void visit(xml::Element* node) override { + for (const xml::Attribute& attr : node->attributes) { + bool create = false; + bool priv = false; + ResourceNameRef nameRef; + if (ResourceParser::tryParseReference(attr.value, &nameRef, &create, &priv)) { + if (create) { + mTable->addResource(nameRef, {}, mSource.line(node->lineNumber), + util::make_unique()); + } + } + } + + for (const auto& child : node->children) { + child->accept(this); + } + } + +private: + Source mSource; + std::shared_ptr mTable; +}; + bool compileXml(const AaptOptions& options, const std::shared_ptr& table, const CompileItem& item, ZipFile* outApk) { std::ifstream in(item.source.path, std::ifstream::binary); @@ -308,20 +343,19 @@ bool compileXml(const AaptOptions& options, const std::shared_ptr return false; } - BigBuffer outBuffer(1024); - - // No resolver, since we are not compiling attributes here. - XmlFlattener flattener(table, {}); - - XmlFlattener::Options xmlOptions; - xmlOptions.defaultPackage = table->getPackage(); - xmlOptions.keepRawValues = true; + SourceLogger logger(item.source); + std::unique_ptr root = xml::inflate(&in, &logger); + if (!root) { + return false; + } - std::shared_ptr parser = std::make_shared(in); + // Collect any resource ID's declared here. + IdCollector idCollector(item.source, table); + root->accept(&idCollector); - Maybe minStrippedSdk = flattener.flatten(item.source, parser, &outBuffer, - xmlOptions); - if (!minStrippedSdk) { + BigBuffer outBuffer(1024); + if (!xml::flatten(root.get(), options.appInfo.package, &outBuffer)) { + logger.error() << "failed to encode XML." << std::endl; return false; } @@ -369,19 +403,13 @@ bool shouldGenerateVersionedResource(const std::shared_ptr& bool linkXml(const AaptOptions& options, const std::shared_ptr& table, const std::shared_ptr& resolver, const LinkItem& item, const void* data, size_t dataLen, ZipFile* outApk, std::queue* outQueue) { - std::shared_ptr tree = std::make_shared(); - if (tree->setTo(data, dataLen, false) != android::NO_ERROR) { + SourceLogger logger(item.source); + std::unique_ptr root = xml::inflate(data, dataLen, &logger); + if (!root) { return false; } - std::shared_ptr parser = std::make_shared(tree); - - BigBuffer outBuffer(1024); - XmlFlattener flattener({}, resolver); - - XmlFlattener::Options xmlOptions; - xmlOptions.defaultPackage = item.originalPackage; - + xml::FlattenOptions xmlOptions; if (options.packageType == AaptOptions::PackageType::StaticLibrary) { xmlOptions.keepRawValues = true; } @@ -392,16 +420,12 @@ bool linkXml(const AaptOptions& options, const std::shared_ptr& t xmlOptions.maxSdkAttribute = item.config.sdkVersion ? item.config.sdkVersion : 1; } - std::shared_ptr binding; - if (item.name.type == ResourceType::kLayout) { - // Layouts may have defined bindings, so we need to make sure they get processed. - binding = std::make_shared(parser); - parser = binding; - } - - Maybe minStrippedSdk = flattener.flatten(item.source, parser, &outBuffer, - xmlOptions); + BigBuffer outBuffer(1024); + Maybe minStrippedSdk = xml::flattenAndLink(item.source, root.get(), + item.originalPackage, resolver, + xmlOptions, &outBuffer); if (!minStrippedSdk) { + logger.error() << "failed to encode XML." << std::endl; return false; } @@ -431,30 +455,6 @@ bool linkXml(const AaptOptions& options, const std::shared_ptr& t << buildFileReference(item) << "' to apk." << std::endl; return false; } - - if (binding && !options.bindingOutput.path.empty()) { - // We generated a binding xml file, write it out. - Source bindingOutput = options.bindingOutput; - appendPath(&bindingOutput.path, buildFileReference(item)); - - if (!mkdirs(bindingOutput.path)) { - Logger::error(bindingOutput) << strerror(errno) << std::endl; - return false; - } - - appendPath(&bindingOutput.path, "bind.xml"); - - std::ofstream bout(bindingOutput.path); - if (!bout) { - Logger::error(bindingOutput) << strerror(errno) << std::endl; - return false; - } - - if (!binding->writeToFile(bout)) { - Logger::error(bindingOutput) << strerror(errno) << std::endl; - return false; - } - } return true; } @@ -504,13 +504,15 @@ bool compileManifest(const AaptOptions& options, const std::shared_ptr xmlParser = std::make_shared(in); - XmlFlattener flattener({}, resolver); + SourceLogger logger(options.manifest); + std::unique_ptr root = xml::inflate(&in, &logger); + if (!root) { + return false; + } - XmlFlattener::Options xmlOptions; - xmlOptions.defaultPackage = options.appInfo.package; - if (!flattener.flatten(options.manifest, xmlParser, &outBuffer, xmlOptions)) { + BigBuffer outBuffer(1024); + if (!xml::flattenAndLink(options.manifest, root.get(), options.appInfo.package, resolver, {}, + &outBuffer)) { return false; } -- cgit v1.2.3-59-g8ed1b