summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/aapt2/cmd/Link.cpp43
-rw-r--r--tools/aapt2/cmd/Optimize.cpp7
-rw-r--r--tools/aapt2/configuration/ConfigurationParser.cpp14
-rw-r--r--tools/aapt2/configuration/ConfigurationParser_test.cpp126
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp141
-rw-r--r--tools/aapt2/optimize/MultiApkGenerator.cpp12
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;