diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/aapt2/cmd/Link.cpp | 43 | ||||
-rw-r--r-- | tools/aapt2/cmd/Optimize.cpp | 7 | ||||
-rw-r--r-- | tools/aapt2/configuration/ConfigurationParser.cpp | 14 | ||||
-rw-r--r-- | tools/aapt2/configuration/ConfigurationParser_test.cpp | 126 | ||||
-rw-r--r-- | tools/aapt2/java/JavaClassGenerator.cpp | 141 | ||||
-rw-r--r-- | tools/aapt2/optimize/MultiApkGenerator.cpp | 12 |
6 files changed, 228 insertions, 115 deletions
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 13dd93e83b64..d782de55f66a 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1069,25 +1069,29 @@ class LinkCommand { bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate, const StringPiece& out_package, const JavaClassGeneratorOptions& java_options, const Maybe<std::string>& out_text_symbols_path = {}) { - if (!options_.generate_java_class_path) { + if (!options_.generate_java_class_path && !out_text_symbols_path) { return true; } - std::string out_path = options_.generate_java_class_path.value(); - file::AppendPath(&out_path, file::PackageToPath(out_package)); - if (!file::mkdirs(out_path)) { - context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path - << "'"); - return false; - } + std::string out_path; + std::unique_ptr<io::FileOutputStream> fout; + if (options_.generate_java_class_path) { + out_path = options_.generate_java_class_path.value(); + file::AppendPath(&out_path, file::PackageToPath(out_package)); + if (!file::mkdirs(out_path)) { + context_->GetDiagnostics()->Error(DiagMessage() + << "failed to create directory '" << out_path << "'"); + return false; + } - file::AppendPath(&out_path, "R.java"); + file::AppendPath(&out_path, "R.java"); - io::FileOutputStream fout(out_path); - if (fout.HadError()) { - context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path - << "': " << fout.GetError()); - return false; + fout = util::make_unique<io::FileOutputStream>(out_path); + if (fout->HadError()) { + context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path + << "': " << fout->GetError()); + return false; + } } std::unique_ptr<io::FileOutputStream> fout_text; @@ -1102,18 +1106,11 @@ class LinkCommand { } JavaClassGenerator generator(context_, table, java_options); - if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) { + if (!generator.Generate(package_name_to_generate, out_package, fout.get(), fout_text.get())) { context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.GetError()); return false; } - fout.Flush(); - - if (fout.HadError()) { - context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path - << "': " << fout.GetError()); - return false; - } return true; } @@ -1934,7 +1931,7 @@ class LinkCommand { return 1; } - if (options_.generate_java_class_path) { + if (options_.generate_java_class_path || options_.generate_text_symbols_path) { if (!GenerateJavaClasses()) { return 1; } diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index 1bdb762528b6..eaadfd82629e 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -327,7 +327,6 @@ int Optimize(const std::vector<StringPiece>& args) { Maybe<std::string> config_path; Maybe<std::string> whitelist_path; Maybe<std::string> target_densities; - Maybe<std::string> target_abis; std::vector<std::string> configs; std::vector<std::string> split_args; std::unordered_set<std::string> kept_artifacts; @@ -349,12 +348,6 @@ int Optimize(const std::vector<StringPiece>& args) { "Path to the whitelist.cfg file containing whitelisted resources \n" "whose names should not be altered in final resource tables.", &whitelist_path) - .OptionalFlag( - "--target-abis", - "Comma separated list of the CPU ABIs that the APK will be optimized for.\n" - "All the native libraries that would be unused on devices of the given ABIs will \n" - "be removed from the APK.", - &target_abis) .OptionalFlagList("-c", "Comma separated list of configurations to include. The default\n" "is all configurations.", diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp index b99240f0a40a..852ff176ed7d 100644 --- a/tools/aapt2/configuration/ConfigurationParser.cpp +++ b/tools/aapt2/configuration/ConfigurationParser.cpp @@ -519,14 +519,22 @@ ConfigurationParser::ActionHandler ConfigurationParser::android_sdk_group_handle } else { AndroidSdk entry; for (const auto& attr : child->attributes) { + Maybe<int>* target = nullptr; if (attr.name == "minSdkVersion") { - entry.min_sdk_version = ResourceUtils::ParseSdkVersion(attr.value); + target = &entry.min_sdk_version; } else if (attr.name == "targetSdkVersion") { - entry.target_sdk_version = ResourceUtils::ParseSdkVersion(attr.value); + target = &entry.target_sdk_version; } else if (attr.name == "maxSdkVersion") { - entry.max_sdk_version = ResourceUtils::ParseSdkVersion(attr.value); + target = &entry.max_sdk_version; } else { diag->Warn(DiagMessage() << "Unknown attribute: " << attr.name << " = " << attr.value); + continue; + } + + *target = ResourceUtils::ParseSdkVersion(attr.value); + if (!*target) { + diag->Error(DiagMessage() << "Invalid attribute: " << attr.name << " = " << attr.value); + valid = false; } } diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp index afa155f46eb9..f7153c822bbc 100644 --- a/tools/aapt2/configuration/ConfigurationParser_test.cpp +++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp @@ -18,8 +18,10 @@ #include <string> +#include "android-base/stringprintf.h" #include "androidfw/ResourceTypes.h" +#include "SdkConstants.h" #include "test/Test.h" #include "xml/XmlDom.h" @@ -35,18 +37,19 @@ void PrintTo(const AndroidSdk& sdk, std::ostream* os) { namespace { +using ::aapt::configuration::Abi; +using ::aapt::configuration::AndroidManifest; +using ::aapt::configuration::AndroidSdk; +using ::aapt::configuration::Artifact; +using ::aapt::configuration::DeviceFeature; +using ::aapt::configuration::GlTexture; +using ::aapt::configuration::Locale; +using ::aapt::configuration::PostProcessingConfiguration; +using ::aapt::xml::Element; +using ::aapt::xml::NodeCast; using ::android::ResTable_config; -using configuration::Abi; -using configuration::AndroidSdk; -using configuration::Artifact; -using configuration::PostProcessingConfiguration; -using configuration::DeviceFeature; -using configuration::GlTexture; -using configuration::Locale; -using configuration::AndroidManifest; +using ::android::base::StringPrintf; using ::testing::ElementsAre; -using xml::Element; -using xml::NodeCast; constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?> <post-process xmlns="http://schemas.android.com/tools/aapt"> @@ -421,17 +424,106 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction) { ASSERT_EQ(sdk, out); } +TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_SingleVersion) { + { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk minSdkVersion="19"></android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_TRUE(ok); + + ASSERT_EQ(1ul, config.android_sdk_groups.size()); + ASSERT_EQ(1u, config.android_sdk_groups.count("v19")); + + auto& out = config.android_sdk_groups["v19"]; + EXPECT_EQ(19, out.min_sdk_version.value()); + EXPECT_FALSE(out.max_sdk_version); + EXPECT_FALSE(out.target_sdk_version); + } + + { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk maxSdkVersion="19"></android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_TRUE(ok); + + ASSERT_EQ(1ul, config.android_sdk_groups.size()); + ASSERT_EQ(1u, config.android_sdk_groups.count("v19")); + + auto& out = config.android_sdk_groups["v19"]; + EXPECT_EQ(19, out.max_sdk_version.value()); + EXPECT_FALSE(out.min_sdk_version); + EXPECT_FALSE(out.target_sdk_version); + } + + { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk targetSdkVersion="19"></android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_TRUE(ok); + + ASSERT_EQ(1ul, config.android_sdk_groups.size()); + ASSERT_EQ(1u, config.android_sdk_groups.count("v19")); + + auto& out = config.android_sdk_groups["v19"]; + EXPECT_EQ(19, out.target_sdk_version.value()); + EXPECT_FALSE(out.min_sdk_version); + EXPECT_FALSE(out.max_sdk_version); + } +} + +TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_InvalidVersion) { + static constexpr const char* xml = R"xml( + <android-sdk-group label="v19"> + <android-sdk + minSdkVersion="v19" + targetSdkVersion="v24" + maxSdkVersion="v25"> + <manifest> + <!--- manifest additions here XSLT? TODO --> + </manifest> + </android-sdk> + </android-sdk-group>)xml"; + + auto doc = test::BuildXmlDom(xml); + + PostProcessingConfiguration config; + bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + ASSERT_FALSE(ok); +} + TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) { static constexpr const char* xml = R"xml( <android-sdk-group label="P"> <android-sdk - minSdkVersion="M" - targetSdkVersion="P" - maxSdkVersion="P"> + minSdkVersion="25" + targetSdkVersion="%s" + maxSdkVersion="%s"> </android-sdk> </android-sdk-group>)xml"; - auto doc = test::BuildXmlDom(xml); + const auto& dev_sdk = GetDevelopmentSdkCodeNameAndVersion(); + const char* codename = dev_sdk.first.data(); + const ApiVersion& version = dev_sdk.second; + + auto doc = test::BuildXmlDom(StringPrintf(xml, codename, codename)); PostProcessingConfiguration config; bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); @@ -443,9 +535,9 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) { auto& out = config.android_sdk_groups["P"]; AndroidSdk sdk; - sdk.min_sdk_version = {}; // Only the latest development version is supported. - sdk.target_sdk_version = 28; - sdk.max_sdk_version = 28; + sdk.min_sdk_version = 25; + sdk.target_sdk_version = version; + sdk.max_sdk_version = version; ASSERT_EQ(sdk, out); } diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 9861770083a2..8c8c2549609a 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -272,7 +272,7 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res // Build the JavaDoc comment for the Styleable array. This has references to child attributes // and what possible values can be used for them. const size_t attr_count = sorted_attributes.size(); - if (attr_count > 0) { + if (out_class_def != nullptr && attr_count > 0) { std::stringstream styleable_comment; if (!styleable.GetComment().empty()) { styleable_comment << styleable.GetComment() << "\n"; @@ -356,54 +356,56 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res continue; } - StringPiece comment = styleable_attr.attr_ref->GetComment(); - if (styleable_attr.symbol.value().attribute && comment.empty()) { - comment = styleable_attr.symbol.value().attribute->GetComment(); - } + if (out_class_def != nullptr) { + StringPiece comment = styleable_attr.attr_ref->GetComment(); + if (styleable_attr.symbol.value().attribute && comment.empty()) { + comment = styleable_attr.symbol.value().attribute->GetComment(); + } - if (comment.contains("@removed")) { - // Removed attributes are public but hidden from the documentation, so - // don't emit them as part of the class documentation. - continue; - } + if (comment.contains("@removed")) { + // Removed attributes are public but hidden from the documentation, so + // don't emit them as part of the class documentation. + continue; + } - const ResourceName& attr_name = styleable_attr.attr_ref->name.value(); + const ResourceName& attr_name = styleable_attr.attr_ref->name.value(); - StringPiece package_name = attr_name.package; - if (package_name.empty()) { - package_name = context_->GetCompilationPackage(); - } + StringPiece package_name = attr_name.package; + if (package_name.empty()) { + package_name = context_->GetCompilationPackage(); + } - std::unique_ptr<IntMember> index_member = util::make_unique<IntMember>( - sorted_attributes[i].field_name, static_cast<uint32_t>(i)); + std::unique_ptr<IntMember> index_member = + util::make_unique<IntMember>(sorted_attributes[i].field_name, static_cast<uint32_t>(i)); + + AnnotationProcessor* attr_processor = index_member->GetCommentBuilder(); + + if (!comment.empty()) { + attr_processor->AppendComment("<p>\n@attr description"); + attr_processor->AppendComment(comment); + } else { + std::stringstream default_comment; + default_comment << "<p>This symbol is the offset where the " + << "{@link " << package_name << ".R.attr#" + << TransformToFieldName(attr_name.entry) << "}\n" + << "attribute's value can be found in the " + << "{@link #" << array_field_name << "} array."; + attr_processor->AppendComment(default_comment.str()); + } - AnnotationProcessor* attr_processor = index_member->GetCommentBuilder(); + attr_processor->AppendNewLine(); + AddAttributeFormatDoc(attr_processor, styleable_attr.symbol.value().attribute.get()); + attr_processor->AppendNewLine(); + attr_processor->AppendComment( + StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data())); - if (!comment.empty()) { - attr_processor->AppendComment("<p>\n@attr description"); - attr_processor->AppendComment(comment); - } else { - std::stringstream default_comment; - default_comment << "<p>This symbol is the offset where the " - << "{@link " << package_name << ".R.attr#" - << TransformToFieldName(attr_name.entry) << "}\n" - << "attribute's value can be found in the " - << "{@link #" << array_field_name << "} array."; - attr_processor->AppendComment(default_comment.str()); + out_class_def->AddMember(std::move(index_member)); } - attr_processor->AppendNewLine(); - AddAttributeFormatDoc(attr_processor, styleable_attr.symbol.value().attribute.get()); - attr_processor->AppendNewLine(); - attr_processor->AppendComment( - StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data())); - if (r_txt_printer != nullptr) { r_txt_printer->Println( StringPrintf("int styleable %s %zd", sorted_attributes[i].field_name.c_str(), i)); } - - out_class_def->AddMember(std::move(index_member)); } // If there is a rewrite method to generate, add the statements that rewrite package IDs @@ -434,31 +436,33 @@ void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const Reso } const std::string field_name = TransformToFieldName(name.entry); - std::unique_ptr<ResourceMember> resource_member = - util::make_unique<ResourceMember>(field_name, real_id); + if (out_class_def != nullptr) { + std::unique_ptr<ResourceMember> resource_member = + util::make_unique<ResourceMember>(field_name, real_id); - // Build the comments and annotations for this entry. - AnnotationProcessor* processor = resource_member->GetCommentBuilder(); + // Build the comments and annotations for this entry. + AnnotationProcessor* processor = resource_member->GetCommentBuilder(); - // Add the comments from any <public> tags. - if (entry.symbol_status.state != SymbolState::kUndefined) { - processor->AppendComment(entry.symbol_status.comment); - } + // Add the comments from any <public> tags. + if (entry.symbol_status.state != SymbolState::kUndefined) { + processor->AppendComment(entry.symbol_status.comment); + } - // Add the comments from all configurations of this entry. - for (const auto& config_value : entry.values) { - processor->AppendComment(config_value->value->GetComment()); - } + // Add the comments from all configurations of this entry. + for (const auto& config_value : entry.values) { + processor->AppendComment(config_value->value->GetComment()); + } - // If this is an Attribute, append the format Javadoc. - if (!entry.values.empty()) { - if (Attribute* attr = ValueCast<Attribute>(entry.values.front()->value.get())) { - // We list out the available values for the given attribute. - AddAttributeFormatDoc(processor, attr); + // If this is an Attribute, append the format Javadoc. + if (!entry.values.empty()) { + if (Attribute* attr = ValueCast<Attribute>(entry.values.front()->value.get())) { + // We list out the available values for the given attribute. + AddAttributeFormatDoc(processor, attr); + } } - } - out_class_def->AddMember(std::move(resource_member)); + out_class_def->AddMember(std::move(resource_member)); + } if (r_txt_printer != nullptr) { r_txt_printer->Print("int ") @@ -576,7 +580,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } // Generate an onResourcesLoaded() callback if requested. - if (options_.rewrite_callback_options) { + if (out != nullptr && options_.rewrite_callback_options) { rewrite_method = util::make_unique<MethodDefinition>("public static void onResourcesLoaded(int p)"); for (const std::string& package_to_callback : @@ -597,8 +601,12 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, const bool force_creation_if_empty = (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic); - std::unique_ptr<ClassDefinition> class_def = util::make_unique<ClassDefinition>( - to_string(type->type), ClassQualifier::kStatic, force_creation_if_empty); + std::unique_ptr<ClassDefinition> class_def; + if (out != nullptr) { + class_def = util::make_unique<ClassDefinition>( + to_string(type->type), ClassQualifier::kStatic, force_creation_if_empty); + } + if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(), rewrite_method.get(), r_txt_printer.get())) { return false; @@ -615,16 +623,17 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } } - if (type->type == ResourceType::kStyleable && + if (out != nullptr && type->type == ResourceType::kStyleable && options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) { // When generating a public R class, we don't want Styleable to be part // of the API. It is only emitted for documentation purposes. class_def->GetCommentBuilder()->AppendComment("@doconly"); } - AppendJavaDocAnnotations(options_.javadoc_annotations, class_def->GetCommentBuilder()); - - r_class.AddMember(std::move(class_def)); + if (out != nullptr) { + AppendJavaDocAnnotations(options_.javadoc_annotations, class_def->GetCommentBuilder()); + r_class.AddMember(std::move(class_def)); + } } } @@ -632,8 +641,10 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, r_class.AddMember(std::move(rewrite_method)); } - AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder()); - ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out); + if (out != nullptr) { + AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder()); + ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out); + } return true; } diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp index da3b8792be69..e2d738aec5a2 100644 --- a/tools/aapt2/optimize/MultiApkGenerator.cpp +++ b/tools/aapt2/optimize/MultiApkGenerator.cpp @@ -17,6 +17,7 @@ #include "MultiApkGenerator.h" #include <algorithm> +#include <regex> #include <string> #include "androidfw/StringPiece.h" @@ -125,6 +126,16 @@ class ContextWrapper : public IAaptContext { int min_sdk_ = -1; }; +class SignatureFilter : public IPathFilter { + bool Keep(const std::string& path) override { + static std::regex signature_regex(R"regex(^META-INF/.*\.(RSA|DSA|EC|SF)$)regex"); + if (std::regex_search(path, signature_regex)) { + return false; + } + return !(path == "META-INF/MANIFEST.MF"); + } +}; + MultiApkGenerator::MultiApkGenerator(LoadedApk* apk, IAaptContext* context) : apk_(apk), context_(context) { } @@ -209,6 +220,7 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) { diag.Note(DiagMessage() << "Writing output: " << out); } + filters.AddFilter(util::make_unique<SignatureFilter>()); if (!apk_->WriteToArchive(&wrapped_context, table.get(), options.table_flattener_options, &filters, writer.get(), manifest.get())) { return false; |