diff options
-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 |