diff options
author | 2017-11-27 13:19:36 -0800 | |
---|---|---|
committer | 2017-12-13 12:28:39 -0800 | |
commit | cb6c3f9b880160c35785b1780b282fdf92952b90 (patch) | |
tree | e3b4211cbcdf9fc23c2cc9134ebc5d2b17e9b50a | |
parent | ff38f236b55b51a9f8e03b909f4791ccca329c48 (diff) |
AAPT2: Push more configuration code into the parser
When parsing is complete, we now have a list of output artifacts that
have their referential integrity validated. This means that once the
configuration file is parsed, the only errors that can occur are related
to APK processing, and not the configuration itself.
This reduces the number of errors that could cause a partial output of
APK artifacts. It simplifies the public API and reduces the complexity of
the code to generate multiple APKs.
Test: Ran unit tests
Test: manually ran the optimize command to ensure it still works
Change-Id: I3f2d885b207a84c958f5348a4baa6718598184a4
-rw-r--r-- | tools/aapt2/cmd/Optimize.cpp | 36 | ||||
-rw-r--r-- | tools/aapt2/configuration/ConfigurationParser.cpp | 365 | ||||
-rw-r--r-- | tools/aapt2/configuration/ConfigurationParser.h | 102 | ||||
-rw-r--r-- | tools/aapt2/configuration/ConfigurationParser.internal.h | 122 | ||||
-rw-r--r-- | tools/aapt2/configuration/ConfigurationParser_test.cpp | 142 | ||||
-rw-r--r-- | tools/aapt2/filter/AbiFilter.cpp | 2 | ||||
-rw-r--r-- | tools/aapt2/optimize/MultiApkGenerator.cpp | 154 | ||||
-rw-r--r-- | tools/aapt2/optimize/MultiApkGenerator.h | 14 | ||||
-rw-r--r-- | tools/aapt2/optimize/MultiApkGenerator_test.cpp | 64 | ||||
-rw-r--r-- | tools/aapt2/test/Builders.cpp | 62 | ||||
-rw-r--r-- | tools/aapt2/test/Builders.h | 32 |
11 files changed, 545 insertions, 550 deletions
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index eaadfd82629e..d8bb9992c152 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -44,8 +44,7 @@ #include "util/Util.h" using ::aapt::configuration::Abi; -using ::aapt::configuration::Artifact; -using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::configuration::OutputArtifact; using ::android::ResTable_config; using ::android::StringPiece; using ::android::base::ReadFileToString; @@ -74,7 +73,7 @@ struct OptimizeOptions { TableFlattenerOptions table_flattener_options; - Maybe<PostProcessingConfiguration> configuration; + Maybe<std::vector<OutputArtifact>> apk_artifacts; // Set of artifacts to keep when generating multi-APK splits. If the list is empty, all artifacts // are kept and will be written as output. @@ -199,14 +198,11 @@ class OptimizeCommand { ++split_constraints_iter; } - if (options_.configuration && options_.output_dir) { + if (options_.apk_artifacts && options_.output_dir) { MultiApkGenerator generator{apk.get(), context_}; MultiApkGeneratorOptions generator_options = { - options_.output_dir.value(), - options_.configuration.value(), - options_.table_flattener_options, - options_.kept_artifacts, - }; + options_.output_dir.value(), options_.apk_artifacts.value(), + options_.table_flattener_options, options_.kept_artifacts}; if (!generator.FromBaseApk(generator_options)) { return 1; } @@ -423,29 +419,27 @@ int Optimize(const std::vector<StringPiece>& args) { std::string& path = config_path.value(); Maybe<ConfigurationParser> for_path = ConfigurationParser::ForPath(path); if (for_path) { - options.configuration = for_path.value().WithDiagnostics(diag).Parse(); + options.apk_artifacts = for_path.value().WithDiagnostics(diag).Parse(apk_path); + if (!options.apk_artifacts) { + diag->Error(DiagMessage() << "Failed to parse the output artifact list"); + return 1; + } + } else { diag->Error(DiagMessage() << "Could not parse config file " << path); return 1; } if (print_only) { - std::vector<std::string> names; - const PostProcessingConfiguration& config = options.configuration.value(); - if (!config.AllArtifactNames(file::GetFilename(apk_path), &names, diag)) { - diag->Error(DiagMessage() << "Failed to generate output artifact list"); - return 1; - } - - for (const auto& name : names) { - std::cout << name << std::endl; + for (const OutputArtifact& artifact : options.apk_artifacts.value()) { + std::cout << artifact.name << std::endl; } return 0; } if (!kept_artifacts.empty()) { - for (const auto& artifact_str : kept_artifacts) { - for (const auto& artifact : util::Tokenize(artifact_str, ',')) { + for (const std::string& artifact_str : kept_artifacts) { + for (const StringPiece& artifact : util::Tokenize(artifact_str, ',')) { options.kept_artifacts.insert(artifact.to_string()); } } diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp index 852ff176ed7d..ebc523f096db 100644 --- a/tools/aapt2/configuration/ConfigurationParser.cpp +++ b/tools/aapt2/configuration/ConfigurationParser.cpp @@ -28,6 +28,7 @@ #include "ConfigDescription.h" #include "Diagnostics.h" #include "ResourceUtils.h" +#include "configuration/ConfigurationParser.internal.h" #include "io/File.h" #include "io/FileSystem.h" #include "io/StringStream.h" @@ -45,11 +46,22 @@ namespace { using ::aapt::configuration::Abi; using ::aapt::configuration::AndroidManifest; using ::aapt::configuration::AndroidSdk; -using ::aapt::configuration::Artifact; -using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::configuration::ConfiguredArtifact; +using ::aapt::configuration::DeviceFeature; +using ::aapt::configuration::Entry; using ::aapt::configuration::GlTexture; using ::aapt::configuration::Group; using ::aapt::configuration::Locale; +using ::aapt::configuration::OutputArtifact; +using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::configuration::handler::AbiGroupTagHandler; +using ::aapt::configuration::handler::AndroidSdkGroupTagHandler; +using ::aapt::configuration::handler::ArtifactFormatTagHandler; +using ::aapt::configuration::handler::ArtifactTagHandler; +using ::aapt::configuration::handler::DeviceFeatureGroupTagHandler; +using ::aapt::configuration::handler::GlTextureGroupTagHandler; +using ::aapt::configuration::handler::LocaleGroupTagHandler; +using ::aapt::configuration::handler::ScreenDensityGroupTagHandler; using ::aapt::io::IFile; using ::aapt::io::RegularFile; using ::aapt::io::StringInputStream; @@ -59,19 +71,16 @@ using ::aapt::xml::NodeCast; using ::aapt::xml::XmlActionExecutor; using ::aapt::xml::XmlActionExecutorPolicy; using ::aapt::xml::XmlNodeAction; -using ::android::base::ReadFileToString; using ::android::StringPiece; +using ::android::base::ReadFileToString; -const std::unordered_map<std::string, Abi> kStringToAbiMap = { +const std::unordered_map<StringPiece, Abi> kStringToAbiMap = { {"armeabi", Abi::kArmeV6}, {"armeabi-v7a", Abi::kArmV7a}, {"arm64-v8a", Abi::kArm64V8a}, {"x86", Abi::kX86}, {"x86_64", Abi::kX86_64}, {"mips", Abi::kMips}, {"mips64", Abi::kMips64}, {"universal", Abi::kUniversal}, }; -const std::map<Abi, std::string> kAbiToStringMap = { - {Abi::kArmeV6, "armeabi"}, {Abi::kArmV7a, "armeabi-v7a"}, {Abi::kArm64V8a, "arm64-v8a"}, - {Abi::kX86, "x86"}, {Abi::kX86_64, "x86_64"}, {Abi::kMips, "mips"}, - {Abi::kMips64, "mips64"}, {Abi::kUniversal, "universal"}, -}; +const std::array<StringPiece, 8> kAbiToStringMap = { + {"armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64", "mips", "mips64", "universal"}}; constexpr const char* kAaptXmlNs = "http://schemas.android.com/tools/aapt"; @@ -106,12 +115,25 @@ class NamespaceVisitor : public xml::Visitor { } }; -} // namespace +/** Copies the values referenced in a configuration group to the target list. */ +template <typename T> +bool CopyXmlReferences(const Maybe<std::string>& name, const Group<T>& groups, + std::vector<T>* target) { + // If there was no item configured, there is nothing to do and no error. + if (!name) { + return true; + } -namespace configuration { + // If the group could not be found, then something is wrong. + auto group = groups.find(name.value()); + if (group == groups.end()) { + return false; + } -const std::string& AbiToString(Abi abi) { - return kAbiToStringMap.find(abi)->second; + for (const T& item : group->second) { + target->push_back(item); + } + return true; } /** @@ -119,8 +141,8 @@ const std::string& AbiToString(Abi abi) { * success, or false if the either the placeholder is not found in the name, or the value is not * present and the placeholder was. */ -static bool ReplacePlaceholder(const StringPiece& placeholder, const Maybe<StringPiece>& value, - std::string* name, IDiagnostics* diag) { +bool ReplacePlaceholder(const StringPiece& placeholder, const Maybe<StringPiece>& value, + std::string* name, IDiagnostics* diag) { size_t offset = name->find(placeholder.data()); bool found = (offset != std::string::npos); @@ -152,6 +174,160 @@ static bool ReplacePlaceholder(const StringPiece& placeholder, const Maybe<Strin } /** + * An ActionHandler for processing XML elements in the XmlActionExecutor. Returns true if the + * element was successfully processed, otherwise returns false. + */ +using ActionHandler = std::function<bool(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag)>; + +/** Binds an ActionHandler to the current configuration being populated. */ +xml::XmlNodeAction::ActionFuncWithDiag Bind(configuration::PostProcessingConfiguration* config, + const ActionHandler& handler) { + return [config, handler](xml::Element* root_element, SourcePathDiagnostics* diag) { + return handler(config, root_element, diag); + }; +} + +/** Returns the binary reprasentation of the XML configuration. */ +Maybe<PostProcessingConfiguration> ExtractConfiguration(const std::string& contents, + IDiagnostics* diag) { + StringInputStream in(contents); + std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, diag, Source("config.xml")); + if (!doc) { + return {}; + } + + // Strip any namespaces from the XML as the XmlActionExecutor ignores anything with a namespace. + Element* root = doc->root.get(); + if (root == nullptr) { + diag->Error(DiagMessage() << "Could not find the root element in the XML document"); + return {}; + } + + std::string& xml_ns = root->namespace_uri; + if (!xml_ns.empty()) { + if (xml_ns != kAaptXmlNs) { + diag->Error(DiagMessage() << "Unknown namespace found on root element: " << xml_ns); + return {}; + } + + xml_ns.clear(); + NamespaceVisitor visitor; + root->Accept(&visitor); + } + + XmlActionExecutor executor; + XmlNodeAction& root_action = executor["post-process"]; + XmlNodeAction& artifacts_action = root_action["artifacts"]; + XmlNodeAction& groups_action = root_action["groups"]; + + PostProcessingConfiguration config; + + // Parse the artifact elements. + artifacts_action["artifact"].Action(Bind(&config, ArtifactTagHandler)); + artifacts_action["artifact-format"].Action(Bind(&config, ArtifactFormatTagHandler)); + + // Parse the different configuration groups. + groups_action["abi-group"].Action(Bind(&config, AbiGroupTagHandler)); + groups_action["screen-density-group"].Action(Bind(&config, ScreenDensityGroupTagHandler)); + groups_action["locale-group"].Action(Bind(&config, LocaleGroupTagHandler)); + groups_action["android-sdk-group"].Action(Bind(&config, AndroidSdkGroupTagHandler)); + groups_action["gl-texture-group"].Action(Bind(&config, GlTextureGroupTagHandler)); + groups_action["device-feature-group"].Action(Bind(&config, DeviceFeatureGroupTagHandler)); + + if (!executor.Execute(XmlActionExecutorPolicy::kNone, diag, doc.get())) { + diag->Error(DiagMessage() << "Could not process XML document"); + return {}; + } + + return {config}; +} + +/** Converts a ConfiguredArtifact into an OutputArtifact. */ +Maybe<OutputArtifact> ToOutputArtifact(const ConfiguredArtifact& artifact, + const std::string& apk_name, + const PostProcessingConfiguration& config, + IDiagnostics* diag) { + if (!artifact.name && !config.artifact_format) { + diag->Error( + DiagMessage() << "Artifact does not have a name and no global name template defined"); + return {}; + } + + Maybe<std::string> artifact_name = + (artifact.name) ? artifact.Name(apk_name, diag) + : artifact.ToArtifactName(config.artifact_format.value(), apk_name, diag); + + if (!artifact_name) { + diag->Error(DiagMessage() << "Could not determine split APK artifact name"); + return {}; + } + + OutputArtifact output_artifact; + output_artifact.name = artifact_name.value(); + + SourcePathDiagnostics src_diag{{output_artifact.name}, diag}; + bool has_errors = false; + + if (!CopyXmlReferences(artifact.abi_group, config.abi_groups, &output_artifact.abis)) { + src_diag.Error(DiagMessage() << "Could not lookup required ABIs: " + << artifact.abi_group.value()); + has_errors = true; + } + + if (!CopyXmlReferences(artifact.locale_group, config.locale_groups, &output_artifact.locales)) { + src_diag.Error(DiagMessage() << "Could not lookup required locales: " + << artifact.locale_group.value()); + has_errors = true; + } + + if (!CopyXmlReferences(artifact.screen_density_group, config.screen_density_groups, + &output_artifact.screen_densities)) { + src_diag.Error(DiagMessage() << "Could not lookup required screen densities: " + << artifact.screen_density_group.value()); + has_errors = true; + } + + if (!CopyXmlReferences(artifact.device_feature_group, config.device_feature_groups, + &output_artifact.features)) { + src_diag.Error(DiagMessage() << "Could not lookup required device features: " + << artifact.device_feature_group.value()); + has_errors = true; + } + + if (!CopyXmlReferences(artifact.gl_texture_group, config.gl_texture_groups, + &output_artifact.textures)) { + src_diag.Error(DiagMessage() << "Could not lookup required OpenGL texture formats: " + << artifact.gl_texture_group.value()); + has_errors = true; + } + + if (artifact.android_sdk_group) { + auto entry = config.android_sdk_groups.find(artifact.android_sdk_group.value()); + if (entry == config.android_sdk_groups.end()) { + src_diag.Error(DiagMessage() << "Could not lookup required Android SDK version: " + << artifact.android_sdk_group.value()); + has_errors = true; + } else { + output_artifact.android_sdk = {entry->second}; + } + } + + if (has_errors) { + return {}; + } + return {output_artifact}; +} + +} // namespace + +namespace configuration { + +const StringPiece& AbiToString(Abi abi) { + return kAbiToStringMap.at(static_cast<size_t>(abi)); +} + +/** * Returns the common artifact base name from a template string. */ Maybe<std::string> ToBaseName(std::string result, const StringPiece& apk_name, IDiagnostics* diag) { @@ -186,8 +362,9 @@ Maybe<std::string> ToBaseName(std::string result, const StringPiece& apk_name, I return result; } -Maybe<std::string> Artifact::ToArtifactName(const StringPiece& format, const StringPiece& apk_name, - IDiagnostics* diag) const { +Maybe<std::string> ConfiguredArtifact::ToArtifactName(const StringPiece& format, + const StringPiece& apk_name, + IDiagnostics* diag) const { Maybe<std::string> base = ToBaseName(format.to_string(), apk_name, diag); if (!base) { return {}; @@ -221,7 +398,7 @@ Maybe<std::string> Artifact::ToArtifactName(const StringPiece& format, const Str return result; } -Maybe<std::string> Artifact::Name(const StringPiece& apk_name, IDiagnostics* diag) const { +Maybe<std::string> ConfiguredArtifact::Name(const StringPiece& apk_name, IDiagnostics* diag) const { if (!name) { return {}; } @@ -229,31 +406,6 @@ Maybe<std::string> Artifact::Name(const StringPiece& apk_name, IDiagnostics* dia return ToBaseName(name.value(), apk_name, diag); } -bool PostProcessingConfiguration::AllArtifactNames(const StringPiece& apk_name, - std::vector<std::string>* artifact_names, - IDiagnostics* diag) const { - for (const auto& artifact : artifacts) { - Maybe<std::string> name; - if (artifact.name) { - name = artifact.Name(apk_name, diag); - } else { - if (!artifact_format) { - diag->Error(DiagMessage() << "No global artifact template and an artifact name is missing"); - return false; - } - name = artifact.ToArtifactName(artifact_format.value(), apk_name, diag); - } - - if (!name) { - return false; - } - - artifact_names->push_back(std::move(name.value())); - } - - return true; -} - } // namespace configuration /** Returns a ConfigurationParser for the file located at the provided path. */ @@ -270,86 +422,58 @@ ConfigurationParser::ConfigurationParser(std::string contents) diag_(&noop_) { } -Maybe<PostProcessingConfiguration> ConfigurationParser::Parse() { - StringInputStream in(contents_); - std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, diag_, Source("config.xml")); - if (!doc) { - return {}; - } - - // Strip any namespaces from the XML as the XmlActionExecutor ignores anything with a namespace. - Element* root = doc->root.get(); - if (root == nullptr) { - diag_->Error(DiagMessage() << "Could not find the root element in the XML document"); - return {}; - } - - std::string& xml_ns = root->namespace_uri; - if (!xml_ns.empty()) { - if (xml_ns != kAaptXmlNs) { - diag_->Error(DiagMessage() << "Unknown namespace found on root element: " << xml_ns); - return {}; - } - - xml_ns.clear(); - NamespaceVisitor visitor; - root->Accept(&visitor); - } - - XmlActionExecutor executor; - XmlNodeAction& root_action = executor["post-process"]; - XmlNodeAction& artifacts_action = root_action["artifacts"]; - XmlNodeAction& groups_action = root_action["groups"]; - - PostProcessingConfiguration config; - - // Helper to bind a static method to an action handler in the DOM executor. - auto bind_handler = - [&config](std::function<bool(PostProcessingConfiguration*, Element*, IDiagnostics*)> h) - -> XmlNodeAction::ActionFuncWithDiag { - return std::bind(h, &config, std::placeholders::_1, std::placeholders::_2); - }; - - // Parse the artifact elements. - artifacts_action["artifact"].Action(bind_handler(artifact_handler_)); - artifacts_action["artifact-format"].Action(bind_handler(artifact_format_handler_)); - - // Parse the different configuration groups. - groups_action["abi-group"].Action(bind_handler(abi_group_handler_)); - groups_action["screen-density-group"].Action(bind_handler(screen_density_group_handler_)); - groups_action["locale-group"].Action(bind_handler(locale_group_handler_)); - groups_action["android-sdk-group"].Action(bind_handler(android_sdk_group_handler_)); - groups_action["gl-texture-group"].Action(bind_handler(gl_texture_group_handler_)); - groups_action["device-feature-group"].Action(bind_handler(device_feature_group_handler_)); - - if (!executor.Execute(XmlActionExecutorPolicy::kNone, diag_, doc.get())) { - diag_->Error(DiagMessage() << "Could not process XML document"); +Maybe<std::vector<OutputArtifact>> ConfigurationParser::Parse( + const android::StringPiece& apk_path) { + Maybe<PostProcessingConfiguration> maybe_config = ExtractConfiguration(contents_, diag_); + if (!maybe_config) { return {}; } - - // TODO: Validate all references in the configuration are valid. It should be safe to assume from - // this point on that any references from one section to another will be present. + const PostProcessingConfiguration& config = maybe_config.value(); // TODO: Automatically arrange artifacts so that they match Play Store multi-APK requirements. // see: https://developer.android.com/google/play/publishing/multiple-apks.html // // For now, make sure the version codes are unique. - std::vector<Artifact>& artifacts = config.artifacts; + std::vector<ConfiguredArtifact> artifacts = config.artifacts; std::sort(artifacts.begin(), artifacts.end()); if (std::adjacent_find(artifacts.begin(), artifacts.end()) != artifacts.end()) { diag_->Error(DiagMessage() << "Configuration has duplicate versions"); return {}; } - return {config}; + const std::string& apk_name = file::GetFilename(apk_path).to_string(); + const StringPiece ext = file::GetExtension(apk_name); + const std::string base_name = apk_name.substr(0, apk_name.size() - ext.size()); + + // Convert from a parsed configuration to a list of artifacts for processing. + std::vector<OutputArtifact> output_artifacts; + bool has_errors = false; + + for (const ConfiguredArtifact& artifact : artifacts) { + Maybe<OutputArtifact> output_artifact = ToOutputArtifact(artifact, apk_name, config, diag_); + if (!output_artifact) { + // Defer return an error condition so that all errors are reported. + has_errors = true; + } else { + output_artifacts.push_back(std::move(output_artifact.value())); + } + } + + if (has_errors) { + return {}; + } + return {output_artifacts}; } -ConfigurationParser::ActionHandler ConfigurationParser::artifact_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +namespace configuration { +namespace handler { + +bool ArtifactTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { // This will be incremented later so the first version will always be different to the base APK. int current_version = (config->artifacts.empty()) ? 0 : config->artifacts.back().version; - Artifact artifact{}; + ConfiguredArtifact artifact{}; Maybe<int> version; for (const auto& attr : root_element->attributes) { if (attr.name == "name") { @@ -380,8 +504,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::artifact_handler_ = return true; }; -ConfigurationParser::ActionHandler ConfigurationParser::artifact_format_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool ArtifactFormatTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* /* diag */) { for (auto& node : root_element->children) { xml::Text* t; if ((t = NodeCast<xml::Text>(node.get())) != nullptr) { @@ -392,8 +516,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::artifact_format_handler_ return true; }; -ConfigurationParser::ActionHandler ConfigurationParser::abi_group_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool AbiGroupTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { std::string label = GetLabel(root_element, diag); if (label.empty()) { return false; @@ -420,8 +544,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::abi_group_handler_ = return valid; }; -ConfigurationParser::ActionHandler ConfigurationParser::screen_density_group_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool ScreenDensityGroupTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { std::string label = GetLabel(root_element, diag); if (label.empty()) { return false; @@ -461,8 +585,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::screen_density_group_han return valid; }; -ConfigurationParser::ActionHandler ConfigurationParser::locale_group_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool LocaleGroupTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { std::string label = GetLabel(root_element, diag); if (label.empty()) { return false; @@ -502,8 +626,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::locale_group_handler_ = return valid; }; -ConfigurationParser::ActionHandler ConfigurationParser::android_sdk_group_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool AndroidSdkGroupTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { std::string label = GetLabel(root_element, diag); if (label.empty()) { return false; @@ -560,8 +684,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::android_sdk_group_handle return valid; }; -ConfigurationParser::ActionHandler ConfigurationParser::gl_texture_group_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool GlTextureGroupTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { std::string label = GetLabel(root_element, diag); if (label.empty()) { return false; @@ -603,8 +727,8 @@ ConfigurationParser::ActionHandler ConfigurationParser::gl_texture_group_handler return valid; }; -ConfigurationParser::ActionHandler ConfigurationParser::device_feature_group_handler_ = - [](PostProcessingConfiguration* config, Element* root_element, IDiagnostics* diag) -> bool { +bool DeviceFeatureGroupTagHandler(PostProcessingConfiguration* config, Element* root_element, + IDiagnostics* diag) { std::string label = GetLabel(root_element, diag); if (label.empty()) { return false; @@ -632,4 +756,7 @@ ConfigurationParser::ActionHandler ConfigurationParser::device_feature_group_han return valid; }; +} // namespace handler +} // namespace configuration + } // namespace aapt diff --git a/tools/aapt2/configuration/ConfigurationParser.h b/tools/aapt2/configuration/ConfigurationParser.h index c5d3284c33f4..ca5891025c92 100644 --- a/tools/aapt2/configuration/ConfigurationParser.h +++ b/tools/aapt2/configuration/ConfigurationParser.h @@ -30,54 +30,6 @@ namespace aapt { namespace configuration { -/** A mapping of group labels to group of configuration items. */ -template<class T> -using Group = std::unordered_map<std::string, std::vector<T>>; - -/** A mapping of group label to a single configuration item. */ -template <class T> -using Entry = std::unordered_map<std::string, T>; - -/** Output artifact configuration options. */ -struct Artifact { - /** Name to use for output of processing foo.apk -> foo.<name>.apk. */ - Maybe<std::string> name; - /** - * Value to add to the base Android manifest versionCode. If it is not present in the - * configuration file, it is set to the previous artifact + 1. If the first artifact does not have - * a value, artifacts are a 1 based index. - */ - int version; - /** If present, uses the ABI group with this name. */ - Maybe<std::string> abi_group; - /** If present, uses the screen density group with this name. */ - Maybe<std::string> screen_density_group; - /** If present, uses the locale group with this name. */ - Maybe<std::string> locale_group; - /** If present, uses the Android SDK group with this name. */ - Maybe<std::string> android_sdk_group; - /** If present, uses the device feature group with this name. */ - Maybe<std::string> device_feature_group; - /** If present, uses the OpenGL texture group with this name. */ - Maybe<std::string> gl_texture_group; - - /** Convert an artifact name template into a name string based on configuration contents. */ - Maybe<std::string> ToArtifactName(const android::StringPiece& format, - const android::StringPiece& apk_name, IDiagnostics* diag) const; - - /** Convert an artifact name template into a name string based on configuration contents. */ - Maybe<std::string> Name(const android::StringPiece& apk_name, IDiagnostics* diag) const; - - bool operator<(const Artifact& rhs) const { - // TODO(safarmer): Order by play store multi-APK requirements. - return version < rhs.version; - } - - bool operator==(const Artifact& rhs) const { - return version == rhs.version; - } -}; - /** Enumeration of currently supported ABIs. */ enum class Abi { kArmeV6, @@ -91,7 +43,7 @@ enum class Abi { }; /** Helper method to convert an ABI to a string representing the path within the APK. */ -const std::string& AbiToString(Abi abi); +const android::StringPiece& AbiToString(Abi abi); /** * Represents an individual locale. When a locale is included, it must be @@ -151,22 +103,16 @@ struct GlTexture { } }; -/** AAPT2 XML configuration file binary representation. */ -struct PostProcessingConfiguration { - // TODO: Support named artifacts? - std::vector<Artifact> artifacts; - Maybe<std::string> artifact_format; - - Group<Abi> abi_groups; - Group<ConfigDescription> screen_density_groups; - Group<ConfigDescription> locale_groups; - Entry<AndroidSdk> android_sdk_groups; - Group<DeviceFeature> device_feature_groups; - Group<GlTexture> gl_texture_groups; - - /** Helper method that generates a list of artifact names and returns true on success. */ - bool AllArtifactNames(const android::StringPiece& apk_name, - std::vector<std::string>* artifact_names, IDiagnostics* diag) const; +/** An artifact with all the details pulled from the PostProcessingConfiguration. */ +struct OutputArtifact { + std::string name; + int version; + std::vector<Abi> abis; + std::vector<ConfigDescription> screen_densities; + std::vector<ConfigDescription> locales; + Maybe<AndroidSdk> android_sdk; + std::vector<DeviceFeature> features; + std::vector<GlTexture> textures; }; } // namespace configuration @@ -202,7 +148,7 @@ class ConfigurationParser { * Parses the configuration file and returns the results. If the configuration could not be parsed * the result is empty and any errors will be displayed with the provided diagnostics context. */ - Maybe<configuration::PostProcessingConfiguration> Parse(); + Maybe<std::vector<configuration::OutputArtifact>> Parse(const android::StringPiece& apk_path); protected: /** @@ -217,30 +163,6 @@ class ConfigurationParser { return diag_; } - /** - * An ActionHandler for processing XML elements in the XmlActionExecutor. Returns true if the - * element was successfully processed, otherwise returns false. - */ - using ActionHandler = std::function<bool(configuration::PostProcessingConfiguration* config, - xml::Element* element, IDiagnostics* diag)>; - - /** Handler for <artifact> tags. */ - static ActionHandler artifact_handler_; - /** Handler for <artifact-format> tags. */ - static ActionHandler artifact_format_handler_; - /** Handler for <abi-group> tags. */ - static ActionHandler abi_group_handler_; - /** Handler for <screen-density-group> tags. */ - static ActionHandler screen_density_group_handler_; - /** Handler for <locale-group> tags. */ - static ActionHandler locale_group_handler_; - /** Handler for <android-sdk-group> tags. */ - static ActionHandler android_sdk_group_handler_; - /** Handler for <gl-texture-group> tags. */ - static ActionHandler gl_texture_group_handler_; - /** Handler for <device-feature-group> tags. */ - static ActionHandler device_feature_group_handler_; - private: /** The contents of the configuration file to parse. */ const std::string contents_; diff --git a/tools/aapt2/configuration/ConfigurationParser.internal.h b/tools/aapt2/configuration/ConfigurationParser.internal.h new file mode 100644 index 000000000000..7657ebd70a8b --- /dev/null +++ b/tools/aapt2/configuration/ConfigurationParser.internal.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAPT2_CONFIGURATIONPARSER_INTERNAL_H +#define AAPT2_CONFIGURATIONPARSER_INTERNAL_H + +namespace aapt { +namespace configuration { + +/** A mapping of group labels to group of configuration items. */ +template <class T> +using Group = std::unordered_map<std::string, std::vector<T>>; + +/** A mapping of group label to a single configuration item. */ +template <class T> +using Entry = std::unordered_map<std::string, T>; + +/** Output artifact configuration options. */ +struct ConfiguredArtifact { + /** Name to use for output of processing foo.apk -> foo.<name>.apk. */ + Maybe<std::string> name; + /** + * Value to add to the base Android manifest versionCode. If it is not present in the + * configuration file, it is set to the previous artifact + 1. If the first artifact does not have + * a value, artifacts are a 1 based index. + */ + int version; + /** If present, uses the ABI group with this name. */ + Maybe<std::string> abi_group; + /** If present, uses the screen density group with this name. */ + Maybe<std::string> screen_density_group; + /** If present, uses the locale group with this name. */ + Maybe<std::string> locale_group; + /** If present, uses the Android SDK group with this name. */ + Maybe<std::string> android_sdk_group; + /** If present, uses the device feature group with this name. */ + Maybe<std::string> device_feature_group; + /** If present, uses the OpenGL texture group with this name. */ + Maybe<std::string> gl_texture_group; + + /** Convert an artifact name template into a name string based on configuration contents. */ + Maybe<std::string> ToArtifactName(const android::StringPiece& format, + const android::StringPiece& apk_name, IDiagnostics* diag) const; + + /** Convert an artifact name template into a name string based on configuration contents. */ + Maybe<std::string> Name(const android::StringPiece& apk_name, IDiagnostics* diag) const; + + bool operator<(const ConfiguredArtifact& rhs) const { + // TODO(safarmer): Order by play store multi-APK requirements. + return version < rhs.version; + } + + bool operator==(const ConfiguredArtifact& rhs) const { + return version == rhs.version; + } +}; + +/** AAPT2 XML configuration file binary representation. */ +struct PostProcessingConfiguration { + // TODO: Support named artifacts? + std::vector<ConfiguredArtifact> artifacts; + Maybe<std::string> artifact_format; + + Group<Abi> abi_groups; + Group<ConfigDescription> screen_density_groups; + Group<ConfigDescription> locale_groups; + Entry<AndroidSdk> android_sdk_groups; + Group<DeviceFeature> device_feature_groups; + Group<GlTexture> gl_texture_groups; +}; + +namespace handler { + +/** Handler for <artifact> tags. */ +bool ArtifactTagHandler(configuration::PostProcessingConfiguration* config, xml::Element* element, + IDiagnostics* diag); + +/** Handler for <artifact-format> tags. */ +bool ArtifactFormatTagHandler(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag); + +/** Handler for <abi-group> tags. */ +bool AbiGroupTagHandler(configuration::PostProcessingConfiguration* config, xml::Element* element, + IDiagnostics* diag); + +/** Handler for <screen-density-group> tags. */ +bool ScreenDensityGroupTagHandler(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag); + +/** Handler for <locale-group> tags. */ +bool LocaleGroupTagHandler(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag); + +/** Handler for <android-sdk-group> tags. */ +bool AndroidSdkGroupTagHandler(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag); + +/** Handler for <gl-texture-group> tags. */ +bool GlTextureGroupTagHandler(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag); + +/** Handler for <device-feature-group> tags. */ +bool DeviceFeatureGroupTagHandler(configuration::PostProcessingConfiguration* config, + xml::Element* element, IDiagnostics* diag); + +} // namespace handler +} // namespace configuration +} // namespace aapt +#endif // AAPT2_CONFIGURATIONPARSER_INTERNAL_H diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp index f7153c822bbc..3f356d78bbfe 100644 --- a/tools/aapt2/configuration/ConfigurationParser_test.cpp +++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp @@ -22,6 +22,7 @@ #include "androidfw/ResourceTypes.h" #include "SdkConstants.h" +#include "configuration/ConfigurationParser.internal.h" #include "test/Test.h" #include "xml/XmlDom.h" @@ -33,14 +34,15 @@ void PrintTo(const AndroidSdk& sdk, std::ostream* os) { << ", target=" << sdk.target_sdk_version.value_or_default(-1) << ", max=" << sdk.max_sdk_version.value_or_default(-1); } -} // namespace configuration + +namespace handler { namespace { using ::aapt::configuration::Abi; using ::aapt::configuration::AndroidManifest; using ::aapt::configuration::AndroidSdk; -using ::aapt::configuration::Artifact; +using ::aapt::configuration::ConfiguredArtifact; using ::aapt::configuration::DeviceFeature; using ::aapt::configuration::GlTexture; using ::aapt::configuration::Locale; @@ -50,6 +52,7 @@ using ::aapt::xml::NodeCast; using ::android::ResTable_config; using ::android::base::StringPrintf; using ::testing::ElementsAre; +using ::testing::SizeIs; constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?> <post-process xmlns="http://schemas.android.com/tools/aapt"> @@ -144,44 +147,47 @@ TEST_F(ConfigurationParserTest, ForPath_NoFile) { TEST_F(ConfigurationParserTest, ValidateFile) { auto parser = ConfigurationParser::ForContents(kValidConfig).WithDiagnostics(&diag_); - auto result = parser.Parse(); + auto result = parser.Parse("test.apk"); ASSERT_TRUE(result); - PostProcessingConfiguration& value = result.value(); - EXPECT_EQ(2ul, value.artifacts.size()); - ASSERT_TRUE(value.artifact_format); - EXPECT_EQ( - "${base}.${abi}.${screen-density}.${locale}.${sdk}.${gl}.${feature}.release", - value.artifact_format.value() - ); - - EXPECT_EQ(2ul, value.abi_groups.size()); - EXPECT_EQ(2ul, value.abi_groups["arm"].size()); - EXPECT_EQ(2ul, value.abi_groups["other"].size()); - - EXPECT_EQ(2ul, value.screen_density_groups.size()); - EXPECT_EQ(3ul, value.screen_density_groups["large"].size()); - EXPECT_EQ(6ul, value.screen_density_groups["alldpi"].size()); - - EXPECT_EQ(2ul, value.locale_groups.size()); - EXPECT_EQ(4ul, value.locale_groups["europe"].size()); - EXPECT_EQ(3ul, value.locale_groups["north-america"].size()); - - EXPECT_EQ(1ul, value.android_sdk_groups.size()); - EXPECT_TRUE(value.android_sdk_groups["v19"].min_sdk_version); - EXPECT_EQ(19, value.android_sdk_groups["v19"].min_sdk_version.value()); - - EXPECT_EQ(1ul, value.gl_texture_groups.size()); - EXPECT_EQ(1ul, value.gl_texture_groups["dxt1"].size()); - - EXPECT_EQ(1ul, value.device_feature_groups.size()); - EXPECT_EQ(1ul, value.device_feature_groups["low-latency"].size()); + const std::vector<OutputArtifact>& value = result.value(); + EXPECT_THAT(value, SizeIs(2ul)); + + const OutputArtifact& a1 = value[0]; + EXPECT_EQ(a1.name, "art1.apk"); + EXPECT_THAT(a1.abis, ElementsAre(Abi::kArmV7a, Abi::kArm64V8a)); + EXPECT_THAT(a1.screen_densities, + ElementsAre(test::ParseConfigOrDie("xhdpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("xxhdpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("xxxhdpi").CopyWithoutSdkVersion())); + EXPECT_THAT(a1.locales, ElementsAre(test::ParseConfigOrDie("en"), test::ParseConfigOrDie("es"), + test::ParseConfigOrDie("fr"), test::ParseConfigOrDie("de"))); + EXPECT_EQ(a1.android_sdk.value().min_sdk_version.value(), 19l); + EXPECT_THAT(a1.textures, SizeIs(1ul)); + EXPECT_THAT(a1.features, SizeIs(1ul)); + + const OutputArtifact& a2 = value[1]; + EXPECT_EQ(a2.name, "art2.apk"); + EXPECT_THAT(a2.abis, ElementsAre(Abi::kX86, Abi::kMips)); + EXPECT_THAT(a2.screen_densities, + ElementsAre(test::ParseConfigOrDie("ldpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("mdpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("hdpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("xhdpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("xxhdpi").CopyWithoutSdkVersion(), + test::ParseConfigOrDie("xxxhdpi").CopyWithoutSdkVersion())); + EXPECT_THAT(a2.locales, + ElementsAre(test::ParseConfigOrDie("en"), test::ParseConfigOrDie("es-rMX"), + test::ParseConfigOrDie("fr-rCA"))); + EXPECT_EQ(a2.android_sdk.value().min_sdk_version.value(), 19l); + EXPECT_THAT(a2.textures, SizeIs(1ul)); + EXPECT_THAT(a2.features, SizeIs(1ul)); } TEST_F(ConfigurationParserTest, InvalidNamespace) { constexpr const char* invalid_ns = R"(<?xml version="1.0" encoding="utf-8" ?> <post-process xmlns="http://schemas.android.com/tools/another-unknown-tool" />)"; - auto result = ConfigurationParser::ForContents(invalid_ns).Parse(); + auto result = ConfigurationParser::ForContents(invalid_ns).Parse("test.apk"); ASSERT_FALSE(result); } @@ -197,9 +203,9 @@ TEST_F(ConfigurationParserTest, ArtifactAction) { gl-texture-group="dxt1" device-feature-group="low-latency"/>)xml"); - ASSERT_TRUE(artifact_handler_(&config, NodeCast<Element>(doc->root.get()), &diag_)); + ASSERT_TRUE(ArtifactTagHandler(&config, NodeCast<Element>(doc->root.get()), &diag_)); - EXPECT_EQ(1ul, config.artifacts.size()); + EXPECT_THAT(config.artifacts, SizeIs(1ul)); auto& artifact = config.artifacts.back(); EXPECT_FALSE(artifact.name); // TODO: make this fail. @@ -223,8 +229,8 @@ TEST_F(ConfigurationParserTest, ArtifactAction) { gl-texture-group="dxt1" device-feature-group="low-latency"/>)xml"); - ASSERT_TRUE(artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); - EXPECT_EQ(2ul, config.artifacts.size()); + ASSERT_TRUE(ArtifactTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); + EXPECT_THAT(config.artifacts, SizeIs(2ul)); EXPECT_EQ(2, config.artifacts.back().version); } @@ -240,8 +246,8 @@ TEST_F(ConfigurationParserTest, ArtifactAction) { gl-texture-group="dxt1" device-feature-group="low-latency"/>)xml"); - ASSERT_TRUE(artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); - EXPECT_EQ(3ul, config.artifacts.size()); + ASSERT_TRUE(ArtifactTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); + EXPECT_THAT(config.artifacts, SizeIs(3ul)); EXPECT_EQ(5, config.artifacts.back().version); } @@ -256,8 +262,8 @@ TEST_F(ConfigurationParserTest, ArtifactAction) { gl-texture-group="dxt1" device-feature-group="low-latency"/>)xml"); - ASSERT_TRUE(artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); - EXPECT_EQ(4ul, config.artifacts.size()); + ASSERT_TRUE(ArtifactTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); + EXPECT_THAT(config.artifacts, SizeIs(4ul)); EXPECT_EQ(6, config.artifacts.back().version); } } @@ -288,7 +294,7 @@ TEST_F(ConfigurationParserTest, DuplicateArtifactVersion) { device-feature-group="low-latency"/> </artifacts> </post-process>)xml"; - auto result = ConfigurationParser::ForContents(configuration).Parse(); + auto result = ConfigurationParser::ForContents(configuration).Parse("test.apk"); ASSERT_FALSE(result); } @@ -299,7 +305,7 @@ TEST_F(ConfigurationParserTest, ArtifactFormatAction) { </artifact-format>)xml"); PostProcessingConfiguration config; - bool ok = artifact_format_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = ArtifactFormatTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_TRUE(config.artifact_format); EXPECT_EQ( @@ -322,10 +328,10 @@ TEST_F(ConfigurationParserTest, AbiGroupAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = abi_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AbiGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); - EXPECT_EQ(1ul, config.abi_groups.size()); + EXPECT_THAT(config.abi_groups, SizeIs(1ul)); ASSERT_EQ(1u, config.abi_groups.count("arm")); auto& out = config.abi_groups["arm"]; @@ -345,11 +351,10 @@ TEST_F(ConfigurationParserTest, ScreenDensityGroupAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = - screen_density_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = ScreenDensityGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); - EXPECT_EQ(1ul, config.screen_density_groups.size()); + EXPECT_THAT(config.screen_density_groups, SizeIs(1ul)); ASSERT_EQ(1u, config.screen_density_groups.count("large")); ConfigDescription xhdpi; @@ -375,7 +380,7 @@ TEST_F(ConfigurationParserTest, LocaleGroupAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = locale_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = LocaleGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_EQ(1ul, config.locale_groups.size()); @@ -407,7 +412,7 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AndroidSdkGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_EQ(1ul, config.android_sdk_groups.size()); @@ -434,7 +439,7 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_SingleVersion) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AndroidSdkGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_EQ(1ul, config.android_sdk_groups.size()); @@ -455,7 +460,7 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_SingleVersion) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AndroidSdkGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_EQ(1ul, config.android_sdk_groups.size()); @@ -476,7 +481,7 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_SingleVersion) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AndroidSdkGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_EQ(1ul, config.android_sdk_groups.size()); @@ -505,7 +510,7 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_InvalidVersion) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AndroidSdkGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_FALSE(ok); } @@ -526,7 +531,7 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) { auto doc = test::BuildXmlDom(StringPrintf(xml, codename, codename)); PostProcessingConfiguration config; - bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = AndroidSdkGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); ASSERT_EQ(1ul, config.android_sdk_groups.size()); @@ -556,10 +561,10 @@ TEST_F(ConfigurationParserTest, GlTextureGroupAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = gl_texture_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = GlTextureGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); - EXPECT_EQ(1ul, config.gl_texture_groups.size()); + EXPECT_THAT(config.gl_texture_groups, SizeIs(1ul)); ASSERT_EQ(1u, config.gl_texture_groups.count("dxt1")); auto& out = config.gl_texture_groups["dxt1"]; @@ -585,11 +590,10 @@ TEST_F(ConfigurationParserTest, DeviceFeatureGroupAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok - = device_feature_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = DeviceFeatureGroupTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); ASSERT_TRUE(ok); - EXPECT_EQ(1ul, config.device_feature_groups.size()); + EXPECT_THAT(config.device_feature_groups, SizeIs(1ul)); ASSERT_EQ(1u, config.device_feature_groups.count("low-latency")); auto& out = config.device_feature_groups["low-latency"]; @@ -603,14 +607,14 @@ TEST_F(ConfigurationParserTest, DeviceFeatureGroupAction) { TEST(ArtifactTest, Simple) { StdErrDiagnostics diag; - Artifact x86; + ConfiguredArtifact x86; x86.abi_group = {"x86"}; auto x86_result = x86.ToArtifactName("something.${abi}.apk", "", &diag); ASSERT_TRUE(x86_result); EXPECT_EQ(x86_result.value(), "something.x86.apk"); - Artifact arm; + ConfiguredArtifact arm; arm.abi_group = {"armeabi-v7a"}; { @@ -640,7 +644,7 @@ TEST(ArtifactTest, Simple) { TEST(ArtifactTest, Complex) { StdErrDiagnostics diag; - Artifact artifact; + ConfiguredArtifact artifact; artifact.abi_group = {"mips64"}; artifact.screen_density_group = {"ldpi"}; artifact.device_feature_group = {"df1"}; @@ -686,7 +690,7 @@ TEST(ArtifactTest, Complex) { TEST(ArtifactTest, Missing) { StdErrDiagnostics diag; - Artifact x86; + ConfiguredArtifact x86; x86.abi_group = {"x86"}; EXPECT_FALSE(x86.ToArtifactName("something.${density}.apk", "", &diag)); @@ -697,7 +701,7 @@ TEST(ArtifactTest, Missing) { TEST(ArtifactTest, Empty) { StdErrDiagnostics diag; - Artifact artifact; + ConfiguredArtifact artifact; EXPECT_FALSE(artifact.ToArtifactName("something.${density}.apk", "", &diag)); EXPECT_TRUE(artifact.ToArtifactName("something.apk", "", &diag)); @@ -707,7 +711,7 @@ TEST(ArtifactTest, Empty) { TEST(ArtifactTest, Repeated) { StdErrDiagnostics diag; - Artifact artifact; + ConfiguredArtifact artifact; artifact.screen_density_group = {"mdpi"}; ASSERT_TRUE(artifact.ToArtifactName("something.${density}.apk", "", &diag)); @@ -717,7 +721,7 @@ TEST(ArtifactTest, Repeated) { TEST(ArtifactTest, Nesting) { StdErrDiagnostics diag; - Artifact x86; + ConfiguredArtifact x86; x86.abi_group = {"x86"}; EXPECT_FALSE(x86.ToArtifactName("something.${abi${density}}.apk", "", &diag)); @@ -729,7 +733,7 @@ TEST(ArtifactTest, Nesting) { TEST(ArtifactTest, Recursive) { StdErrDiagnostics diag; - Artifact artifact; + ConfiguredArtifact artifact; artifact.device_feature_group = {"${gl}"}; artifact.gl_texture_group = {"glx1"}; @@ -755,4 +759,6 @@ TEST(ArtifactTest, Recursive) { } } // namespace +} // namespace handler +} // namespace configuration } // namespace aapt diff --git a/tools/aapt2/filter/AbiFilter.cpp b/tools/aapt2/filter/AbiFilter.cpp index cb96235f98f9..9ace82ad4af7 100644 --- a/tools/aapt2/filter/AbiFilter.cpp +++ b/tools/aapt2/filter/AbiFilter.cpp @@ -25,7 +25,7 @@ namespace aapt { std::unique_ptr<AbiFilter> AbiFilter::FromAbiList(const std::vector<configuration::Abi>& abi_list) { std::unordered_set<std::string> abi_set; for (auto& abi : abi_list) { - abi_set.insert(configuration::AbiToString(abi)); + abi_set.insert(configuration::AbiToString(abi).to_string()); } // Make unique by hand as the constructor is private. return std::unique_ptr<AbiFilter>(new AbiFilter(abi_set)); diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp index e2d738aec5a2..16898d6f3e03 100644 --- a/tools/aapt2/optimize/MultiApkGenerator.cpp +++ b/tools/aapt2/optimize/MultiApkGenerator.cpp @@ -40,33 +40,11 @@ namespace aapt { using ::aapt::configuration::AndroidSdk; -using ::aapt::configuration::Artifact; -using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::configuration::OutputArtifact; using ::aapt::xml::kSchemaAndroid; using ::aapt::xml::XmlResource; using ::android::StringPiece; -namespace { - -Maybe<AndroidSdk> GetAndroidSdk(const Artifact& artifact, const PostProcessingConfiguration& config, - IDiagnostics* diag) { - if (!artifact.android_sdk_group) { - return {}; - } - - const std::string& group_name = artifact.android_sdk_group.value(); - auto group = config.android_sdk_groups.find(group_name); - // TODO: Remove validation when configuration parser ensures referential integrity. - if (group == config.android_sdk_groups.end()) { - diag->Error(DiagMessage() << "could not find referenced group '" << group_name << "'"); - return {}; - } - - return group->second; -} - -} // namespace - /** * Context wrapper that allows the min Android SDK value to be overridden. */ @@ -115,8 +93,9 @@ class ContextWrapper : public IAaptContext { min_sdk_ = min_sdk; } - void SetSource(const Source& source) { - source_diag_ = util::make_unique<SourcePathDiagnostics>(source, context_->GetDiagnostics()); + void SetSource(const std::string& source) { + source_diag_ = + util::make_unique<SourcePathDiagnostics>(Source{source}, context_->GetDiagnostics()); } private: @@ -142,82 +121,60 @@ MultiApkGenerator::MultiApkGenerator(LoadedApk* apk, IAaptContext* context) bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) { // TODO(safarmer): Handle APK version codes for the generated APKs. - const PostProcessingConfiguration& config = options.config; - - const std::string& apk_name = file::GetFilename(apk_->GetSource().path).to_string(); - const StringPiece ext = file::GetExtension(apk_name); - const std::string base_name = apk_name.substr(0, apk_name.rfind(ext.to_string())); std::unordered_set<std::string> artifacts_to_keep = options.kept_artifacts; std::unordered_set<std::string> filtered_artifacts; std::unordered_set<std::string> kept_artifacts; // For now, just write out the stripped APK since ABI splitting doesn't modify anything else. - for (const Artifact& artifact : config.artifacts) { - SourcePathDiagnostics diag{{apk_name}, context_->GetDiagnostics()}; - + for (const OutputArtifact& artifact : options.apk_artifacts) { FilterChain filters; - if (!artifact.name && !config.artifact_format) { - diag.Error( - DiagMessage() << "Artifact does not have a name and no global name template defined"); - return false; - } - - Maybe<std::string> maybe_artifact_name = - (artifact.name) ? artifact.Name(apk_name, &diag) - : artifact.ToArtifactName(config.artifact_format.value(), apk_name, &diag); - - if (!maybe_artifact_name) { - diag.Error(DiagMessage() << "Could not determine split APK artifact name"); - return false; - } - - const std::string& artifact_name = maybe_artifact_name.value(); - ContextWrapper wrapped_context{context_}; - wrapped_context.SetSource({artifact_name}); + wrapped_context.SetSource(artifact.name); if (!options.kept_artifacts.empty()) { - const auto& it = artifacts_to_keep.find(artifact_name); + const auto& it = artifacts_to_keep.find(artifact.name); if (it == artifacts_to_keep.end()) { - filtered_artifacts.insert(artifact_name); + filtered_artifacts.insert(artifact.name); if (context_->IsVerbose()) { - context_->GetDiagnostics()->Note(DiagMessage(artifact_name) << "skipping artifact"); + context_->GetDiagnostics()->Note(DiagMessage(artifact.name) << "skipping artifact"); } continue; } else { artifacts_to_keep.erase(it); - kept_artifacts.insert(artifact_name); + kept_artifacts.insert(artifact.name); } } std::unique_ptr<ResourceTable> table = - FilterTable(artifact, config, *apk_->GetResourceTable(), &wrapped_context, &filters); + FilterTable(context_, artifact, *apk_->GetResourceTable(), &filters); if (!table) { return false; } + IDiagnostics* diag = wrapped_context.GetDiagnostics(); + std::unique_ptr<XmlResource> manifest; - if (!UpdateManifest(artifact, config, &manifest, &diag)) { - diag.Error(DiagMessage() << "could not update AndroidManifest.xml for output artifact"); + if (!UpdateManifest(artifact, &manifest, diag)) { + diag->Error(DiagMessage() << "could not update AndroidManifest.xml for output artifact"); return false; } std::string out = options.out_dir; if (!file::mkdirs(out)) { - diag.Warn(DiagMessage() << "could not create out dir: " << out); + diag->Warn(DiagMessage() << "could not create out dir: " << out); } - file::AppendPath(&out, artifact_name); + file::AppendPath(&out, artifact.name); if (context_->IsVerbose()) { - diag.Note(DiagMessage() << "Generating split: " << out); + diag->Note(DiagMessage() << "Generating split: " << out); } - std::unique_ptr<IArchiveWriter> writer = CreateZipFileArchiveWriter(&diag, out); + std::unique_ptr<IArchiveWriter> writer = CreateZipFileArchiveWriter(diag, out); if (context_->IsVerbose()) { - diag.Note(DiagMessage() << "Writing output: " << out); + diag->Note(DiagMessage() << "Writing output: " << out); } filters.AddFilter(util::make_unique<SignatureFilter>()); @@ -254,64 +211,34 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) { return true; } -std::unique_ptr<ResourceTable> MultiApkGenerator::FilterTable( - const configuration::Artifact& artifact, - const configuration::PostProcessingConfiguration& config, const ResourceTable& old_table, - IAaptContext* context, FilterChain* filters) { +std::unique_ptr<ResourceTable> MultiApkGenerator::FilterTable(IAaptContext* context, + const OutputArtifact& artifact, + const ResourceTable& old_table, + FilterChain* filters) { TableSplitterOptions splits; AxisConfigFilter axis_filter; ContextWrapper wrapped_context{context}; + wrapped_context.SetSource(artifact.name); - if (artifact.abi_group) { - const std::string& group_name = artifact.abi_group.value(); - - auto group = config.abi_groups.find(group_name); - // TODO: Remove validation when configuration parser ensures referential integrity. - if (group == config.abi_groups.end()) { - context->GetDiagnostics()->Error(DiagMessage() << "could not find referenced ABI group '" - << group_name << "'"); - return {}; - } - filters->AddFilter(AbiFilter::FromAbiList(group->second)); + if (!artifact.abis.empty()) { + filters->AddFilter(AbiFilter::FromAbiList(artifact.abis)); } - if (artifact.screen_density_group) { - const std::string& group_name = artifact.screen_density_group.value(); - - auto group = config.screen_density_groups.find(group_name); - // TODO: Remove validation when configuration parser ensures referential integrity. - if (group == config.screen_density_groups.end()) { - context->GetDiagnostics()->Error(DiagMessage() - << "could not find referenced group '" << group_name << "'"); - return {}; - } - - const std::vector<ConfigDescription>& densities = group->second; - for (const auto& density_config : densities) { + if (!artifact.screen_densities.empty()) { + for (const auto& density_config : artifact.screen_densities) { splits.preferred_densities.push_back(density_config.density); } } - if (artifact.locale_group) { - const std::string& group_name = artifact.locale_group.value(); - auto group = config.locale_groups.find(group_name); - // TODO: Remove validation when configuration parser ensures referential integrity. - if (group == config.locale_groups.end()) { - context->GetDiagnostics()->Error(DiagMessage() - << "could not find referenced group '" << group_name << "'"); - return {}; - } - - const std::vector<ConfigDescription>& locales = group->second; - for (const auto& locale : locales) { + if (!artifact.locales.empty()) { + for (const auto& locale : artifact.locales) { axis_filter.AddConfig(locale); } splits.config_filter = &axis_filter; } - Maybe<AndroidSdk> sdk = GetAndroidSdk(artifact, config, context->GetDiagnostics()); - if (sdk && sdk.value().min_sdk_version) { - wrapped_context.SetMinSdkVersion(sdk.value().min_sdk_version.value()); + if (artifact.android_sdk && artifact.android_sdk.value().min_sdk_version) { + wrapped_context.SetMinSdkVersion(artifact.android_sdk.value().min_sdk_version.value()); } std::unique_ptr<ResourceTable> table = old_table.Clone(); @@ -327,8 +254,7 @@ std::unique_ptr<ResourceTable> MultiApkGenerator::FilterTable( return table; } -bool MultiApkGenerator::UpdateManifest(const Artifact& artifact, - const PostProcessingConfiguration& config, +bool MultiApkGenerator::UpdateManifest(const OutputArtifact& artifact, std::unique_ptr<XmlResource>* updated_manifest, IDiagnostics* diag) { const xml::XmlResource* apk_manifest = apk_->GetManifest(); @@ -367,10 +293,9 @@ bool MultiApkGenerator::UpdateManifest(const Artifact& artifact, versionCode->compiled_value = ResourceUtils::TryParseInt(std::to_string(new_version)); // Check to see if the minSdkVersion needs to be updated. - Maybe<AndroidSdk> maybe_sdk = GetAndroidSdk(artifact, config, diag); - if (maybe_sdk) { + if (artifact.android_sdk) { // TODO(safarmer): Handle the rest of the Android SDK. - const AndroidSdk& android_sdk = maybe_sdk.value(); + const AndroidSdk& android_sdk = artifact.android_sdk.value(); if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) { if (xml::Attribute* min_sdk_attr = @@ -392,10 +317,7 @@ bool MultiApkGenerator::UpdateManifest(const Artifact& artifact, } } - if (artifact.screen_density_group) { - auto densities = config.screen_density_groups.find(artifact.screen_density_group.value()); - CHECK(densities != config.screen_density_groups.end()) << "Missing density group"; - + if (!artifact.screen_densities.empty()) { xml::Element* screens_el = manifest_el->FindChild({}, "compatible-screens"); if (!screens_el) { // create a new element. @@ -408,7 +330,7 @@ bool MultiApkGenerator::UpdateManifest(const Artifact& artifact, screens_el->GetChildElements().clear(); } - for (const auto& density : densities->second) { + for (const auto& density : artifact.screen_densities) { std::unique_ptr<xml::Element> screen_el = util::make_unique<xml::Element>(); screen_el->name = "screen"; const char* density_str = density.toString().string(); diff --git a/tools/aapt2/optimize/MultiApkGenerator.h b/tools/aapt2/optimize/MultiApkGenerator.h index dedb610e1caa..19f64cc0e588 100644 --- a/tools/aapt2/optimize/MultiApkGenerator.h +++ b/tools/aapt2/optimize/MultiApkGenerator.h @@ -20,6 +20,7 @@ #include <memory> #include <string> #include <unordered_set> +#include <vector> #include "Diagnostics.h" #include "LoadedApk.h" @@ -29,7 +30,7 @@ namespace aapt { struct MultiApkGeneratorOptions { std::string out_dir; - configuration::PostProcessingConfiguration config; + std::vector<configuration::OutputArtifact> apk_artifacts; TableFlattenerOptions table_flattener_options; std::unordered_set<std::string> kept_artifacts; }; @@ -49,18 +50,17 @@ class MultiApkGenerator { bool FromBaseApk(const MultiApkGeneratorOptions& options); protected: - virtual std::unique_ptr<ResourceTable> FilterTable( - const configuration::Artifact& artifact, - const configuration::PostProcessingConfiguration& config, const ResourceTable& old_table, - IAaptContext* context, FilterChain* chain); + virtual std::unique_ptr<ResourceTable> FilterTable(IAaptContext* context, + const configuration::OutputArtifact& artifact, + const ResourceTable& old_table, + FilterChain* chain); private: IDiagnostics* GetDiagnostics() { return context_->GetDiagnostics(); } - bool UpdateManifest(const configuration::Artifact& artifact, - const configuration::PostProcessingConfiguration& config, + bool UpdateManifest(const configuration::OutputArtifact& artifact, std::unique_ptr<xml::XmlResource>* updated_manifest, IDiagnostics* diag); LoadedApk* apk_; diff --git a/tools/aapt2/optimize/MultiApkGenerator_test.cpp b/tools/aapt2/optimize/MultiApkGenerator_test.cpp index 2d303e220f8f..e1d951fc9776 100644 --- a/tools/aapt2/optimize/MultiApkGenerator_test.cpp +++ b/tools/aapt2/optimize/MultiApkGenerator_test.cpp @@ -36,8 +36,7 @@ namespace { using ::aapt::configuration::Abi; using ::aapt::configuration::AndroidSdk; -using ::aapt::configuration::Artifact; -using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::configuration::OutputArtifact; using ::aapt::test::GetValue; using ::aapt::test::GetValueForConfig; using ::aapt::test::ParseConfigOrDie; @@ -48,7 +47,6 @@ using ::testing::NotNull; using ::testing::PrintToString; using ::testing::Return; using ::testing::Test; -using ::testing::_; /** * Subclass the MultiApkGenerator class so that we can access the protected FilterTable method to @@ -60,11 +58,11 @@ class MultiApkGeneratorWrapper : public MultiApkGenerator { : MultiApkGenerator(apk, context) { } - std::unique_ptr<ResourceTable> FilterTable( - const configuration::Artifact& artifact, - const configuration::PostProcessingConfiguration& config, const ResourceTable& old_table, - IAaptContext* context, FilterChain* filter_chain) override { - return MultiApkGenerator::FilterTable(artifact, config, old_table, context, filter_chain); + std::unique_ptr<ResourceTable> FilterTable(IAaptContext* context, + const configuration::OutputArtifact& artifact, + const ResourceTable& old_table, + FilterChain* filter_chain) override { + return MultiApkGenerator::FilterTable(context, artifact, old_table, filter_chain); } }; @@ -108,27 +106,13 @@ TEST_F(MultiApkGeneratorTest, VersionFilterNewerVersion) { LoadedApk apk = {{"test.apk"}, {}, std::move(table), {}}; std::unique_ptr<IAaptContext> ctx = test::ContextBuilder().SetMinSdkVersion(19).Build(); - PostProcessingConfiguration empty_config; - TableFlattenerOptions table_flattener_options; FilterChain chain; - Artifact x64 = test::ArtifactBuilder() - .SetName("${basename}.${sdk}.apk") - .SetDensityGroup("xhdpi") - .SetAndroidSdk("v23") - .Build(); - - auto config = test::PostProcessingConfigurationBuilder() - .SetLocaleGroup("en", {"en"}) - .SetAbiGroup("x64", {Abi::kX86_64}) - .SetDensityGroup("xhdpi", {"xhdpi"}) - .SetAndroidSdk("v23", AndroidSdk::ForMinSdk(23)) - .AddArtifact(x64) - .Build(); + OutputArtifact artifact = test::ArtifactBuilder().AddDensity(xhdpi_).SetAndroidSdk(23).Build(); MultiApkGeneratorWrapper generator{&apk, ctx.get()}; std::unique_ptr<ResourceTable> split = - generator.FilterTable(x64, config, *apk.GetResourceTable(), ctx.get(), &chain); + generator.FilterTable(ctx.get(), artifact, *apk.GetResourceTable(), &chain); ResourceTable* new_table = split.get(); EXPECT_THAT(ValueForConfig(new_table, mdpi_), IsNull()); @@ -149,27 +133,13 @@ TEST_F(MultiApkGeneratorTest, VersionFilterOlderVersion) { LoadedApk apk = {{"test.apk"}, {}, std::move(table), {}}; std::unique_ptr<IAaptContext> ctx = test::ContextBuilder().SetMinSdkVersion(1).Build(); - PostProcessingConfiguration empty_config; - TableFlattenerOptions table_flattener_options; FilterChain chain; - Artifact x64 = test::ArtifactBuilder() - .SetName("${basename}.${sdk}.apk") - .SetDensityGroup("xhdpi") - .SetAndroidSdk("v4") - .Build(); - - auto config = test::PostProcessingConfigurationBuilder() - .SetLocaleGroup("en", {"en"}) - .SetAbiGroup("x64", {Abi::kX86_64}) - .SetDensityGroup("xhdpi", {"xhdpi"}) - .SetAndroidSdk("v4", AndroidSdk::ForMinSdk(4)) - .AddArtifact(x64) - .Build(); + OutputArtifact artifact = test::ArtifactBuilder().AddDensity(xhdpi_).SetAndroidSdk(4).Build(); MultiApkGeneratorWrapper generator{&apk, ctx.get()};; std::unique_ptr<ResourceTable> split = - generator.FilterTable(x64, config, *apk.GetResourceTable(), ctx.get(), &chain); + generator.FilterTable(ctx.get(), artifact, *apk.GetResourceTable(), &chain); ResourceTable* new_table = split.get(); EXPECT_THAT(ValueForConfig(new_table, mdpi_), IsNull()); @@ -188,23 +158,13 @@ TEST_F(MultiApkGeneratorTest, VersionFilterNoVersion) { LoadedApk apk = {{"test.apk"}, {}, std::move(table), {}}; std::unique_ptr<IAaptContext> ctx = test::ContextBuilder().SetMinSdkVersion(1).Build(); - PostProcessingConfiguration empty_config; - TableFlattenerOptions table_flattener_options; FilterChain chain; - Artifact x64 = - test::ArtifactBuilder().SetName("${basename}.${sdk}.apk").SetDensityGroup("xhdpi").Build(); - - auto config = test::PostProcessingConfigurationBuilder() - .SetLocaleGroup("en", {"en"}) - .SetAbiGroup("x64", {Abi::kX86_64}) - .SetDensityGroup("xhdpi", {"xhdpi"}) - .AddArtifact(x64) - .Build(); + OutputArtifact artifact = test::ArtifactBuilder().AddDensity(xhdpi_).Build(); MultiApkGeneratorWrapper generator{&apk, ctx.get()}; std::unique_ptr<ResourceTable> split = - generator.FilterTable(x64, config, *apk.GetResourceTable(), ctx.get(), &chain); + generator.FilterTable(ctx.get(), artifact, *apk.GetResourceTable(), &chain); ResourceTable* new_table = split.get(); EXPECT_THAT(ValueForConfig(new_table, mdpi_), IsNull()); diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp index ecec63f3cf31..88897a8afac3 100644 --- a/tools/aapt2/test/Builders.cpp +++ b/tools/aapt2/test/Builders.cpp @@ -25,7 +25,7 @@ using ::aapt::configuration::Abi; using ::aapt::configuration::AndroidSdk; -using ::aapt::configuration::Artifact; +using ::aapt::configuration::ConfiguredArtifact; using ::aapt::io::StringInputStream; using ::android::StringPiece; @@ -221,72 +221,32 @@ std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* contex return doc; } -PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetAbiGroup( - const std::string& name, const std::vector<Abi>& abis) { - config_.abi_groups[name] = abis; - return *this; -} - -PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetLocaleGroup( - const std::string& name, const std::vector<std::string>& locales) { - auto& group = config_.locale_groups[name]; - for (const auto& locale : locales) { - group.push_back(ParseConfigOrDie(locale)); - } - return *this; -} - -PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetDensityGroup( - const std::string& name, const std::vector<std::string>& densities) { - auto& group = config_.screen_density_groups[name]; - for (const auto& density : densities) { - group.push_back(ParseConfigOrDie(density)); - } - return *this; -} - -PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetAndroidSdk( - const std::string& name, const AndroidSdk& sdk) { - config_.android_sdk_groups[name] = sdk; - return *this; -} - -PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddArtifact( - const Artifact& artifact) { - config_.artifacts.push_back(artifact); - return *this; -} - -configuration::PostProcessingConfiguration PostProcessingConfigurationBuilder::Build() { - return config_; -} - ArtifactBuilder& ArtifactBuilder::SetName(const std::string& name) { - artifact_.name = {name}; + artifact_.name = name; return *this; } -ArtifactBuilder& ArtifactBuilder::SetAbiGroup(const std::string& name) { - artifact_.abi_group = {name}; +ArtifactBuilder& ArtifactBuilder::AddAbi(configuration::Abi abi) { + artifact_.abis.push_back(abi); return *this; } -ArtifactBuilder& ArtifactBuilder::SetDensityGroup(const std::string& name) { - artifact_.screen_density_group = {name}; +ArtifactBuilder& ArtifactBuilder::AddDensity(const ConfigDescription& density) { + artifact_.screen_densities.push_back(density); return *this; } -ArtifactBuilder& ArtifactBuilder::SetLocaleGroup(const std::string& name) { - artifact_.locale_group = {name}; +ArtifactBuilder& ArtifactBuilder::AddLocale(const ConfigDescription& locale) { + artifact_.locales.push_back(locale); return *this; } -ArtifactBuilder& ArtifactBuilder::SetAndroidSdk(const std::string& name) { - artifact_.android_sdk_group = {name}; +ArtifactBuilder& ArtifactBuilder::SetAndroidSdk(int min_sdk) { + artifact_.android_sdk = {AndroidSdk::ForMinSdk(min_sdk)}; return *this; } -configuration::Artifact ArtifactBuilder::Build() { +configuration::OutputArtifact ArtifactBuilder::Build() { return artifact_; } diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index 4cdfc33e92e3..2f83b78ffb2a 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -25,6 +25,7 @@ #include "ResourceTable.h" #include "ResourceValues.h" #include "configuration/ConfigurationParser.h" +#include "configuration/ConfigurationParser.internal.h" #include "process/IResourceTableConsumer.h" #include "test/Common.h" #include "util/Maybe.h" @@ -154,38 +155,19 @@ std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str); std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context, const android::StringPiece& str); -class PostProcessingConfigurationBuilder { - public: - PostProcessingConfigurationBuilder() = default; - - PostProcessingConfigurationBuilder& SetAbiGroup(const std::string& name, - const std::vector<configuration::Abi>& abis); - PostProcessingConfigurationBuilder& SetLocaleGroup(const std::string& name, - const std::vector<std::string>& locales); - PostProcessingConfigurationBuilder& SetDensityGroup(const std::string& name, - const std::vector<std::string>& densities); - PostProcessingConfigurationBuilder& SetAndroidSdk(const std::string& name, - const configuration::AndroidSdk& sdk); - PostProcessingConfigurationBuilder& AddArtifact(const configuration::Artifact& artifact); - configuration::PostProcessingConfiguration Build(); - - private: - configuration::PostProcessingConfiguration config_; -}; - class ArtifactBuilder { public: ArtifactBuilder() = default; ArtifactBuilder& SetName(const std::string& name); - ArtifactBuilder& SetAbiGroup(const std::string& name); - ArtifactBuilder& SetDensityGroup(const std::string& name); - ArtifactBuilder& SetLocaleGroup(const std::string& name); - ArtifactBuilder& SetAndroidSdk(const std::string& name); - configuration::Artifact Build(); + ArtifactBuilder& AddAbi(configuration::Abi abi); + ArtifactBuilder& AddDensity(const ConfigDescription& density); + ArtifactBuilder& AddLocale(const ConfigDescription& locale); + ArtifactBuilder& SetAndroidSdk(int min_sdk); + configuration::OutputArtifact Build(); private: - configuration::Artifact artifact_; + configuration::OutputArtifact artifact_; }; } // namespace test |