AAPT2: Add --package-id flag for feature-split suppport
Bug: 35928935
Change-Id: Ia8496505e61cfcfdb8f9f62366d2f36e453db111
Test: make aapt2_tests
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index dd8e14b..c8f0217 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -23,6 +23,7 @@
#include "android-base/errors.h"
#include "android-base/file.h"
+#include "android-base/stringprintf.h"
#include "androidfw/StringPiece.h"
#include "google/protobuf/io/coded_stream.h"
@@ -57,6 +58,7 @@
#include "xml/XmlDom.h"
using android::StringPiece;
+using android::base::StringPrintf;
using ::google::protobuf::io::CopyingOutputStreamAdaptor;
namespace aapt {
@@ -705,11 +707,17 @@
}
// If we are using --no-static-lib-packages, we need to rename the
- // package of this
- // table to our compilation package.
+ // package of this table to our compilation package.
if (options_.no_static_lib_packages) {
- if (ResourceTablePackage* pkg = include_static->FindPackageById(0x7f)) {
+ // Since package names can differ, and multiple packages can exist in a ResourceTable,
+ // we place the requirement that all static libraries are built with the package
+ // ID 0x7f. So if one is not found, this is an error.
+ if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) {
pkg->name = context_->GetCompilationPackage();
+ } else {
+ context_->GetDiagnostics()->Error(DiagMessage(path)
+ << "no package with ID 0x7f found in static library");
+ return false;
}
}
@@ -733,7 +741,7 @@
// Capture the shared libraries so that the final resource table can be properly flattened
// with support for shared libraries.
for (auto& entry : asset_source->GetAssignedPackageIds()) {
- if (entry.first > 0x01 && entry.first < 0x7f) {
+ if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) {
final_table_.included_packages_[entry.first] = entry.second;
}
}
@@ -860,10 +868,9 @@
for (const auto& package : final_table_.packages) {
for (const auto& type : package->types) {
if (type->id) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "type " << type->type << " has ID " << std::hex
- << (int)type->id.value() << std::dec
- << " assigned");
+ context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
+ << StringPrintf("%02x", type->id.value())
+ << " assigned");
return false;
}
@@ -871,9 +878,8 @@
if (entry->id) {
ResourceNameRef res_name(package->name, type->type, entry->name);
context_->GetDiagnostics()->Error(
- DiagMessage() << "entry " << res_name << " has ID " << std::hex
- << (int)entry->id.value() << std::dec
- << " assigned");
+ DiagMessage() << "entry " << res_name << " has ID "
+ << StringPrintf("%02x", entry->id.value()) << " assigned");
return false;
}
}
@@ -1103,7 +1109,7 @@
return false;
}
- ResourceTablePackage* pkg = table->FindPackageById(0x7f);
+ ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
if (!pkg) {
context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
return false;
@@ -1490,12 +1496,17 @@
context_->SetNameManglerPolicy(
NameManglerPolicy{context_->GetCompilationPackage()});
- if (options_.package_type == PackageType::kSharedLib) {
- context_->SetPackageId(0x00);
- } else if (context_->GetCompilationPackage() == "android") {
+
+ // Override the package ID when it is "android".
+ if (context_->GetCompilationPackage() == "android") {
context_->SetPackageId(0x01);
- } else {
- context_->SetPackageId(0x7f);
+
+ // Verify we're building a regular app.
+ if (options_.package_type != PackageType::kApp) {
+ context_->GetDiagnostics()->Error(
+ DiagMessage() << "package 'android' can only be built as a regular app");
+ return 1;
+ }
}
if (!LoadSymbolsFromIncludePaths()) {
@@ -1509,10 +1520,9 @@
if (context_->IsVerbose()) {
context_->GetDiagnostics()->Note(DiagMessage()
- << "linking package '"
- << context_->GetCompilationPackage()
- << "' with package ID " << std::hex
- << (int)context_->GetPackageId());
+ << StringPrintf("linking package '%s' using package ID %02x",
+ context_->GetCompilationPackage().data(),
+ context_->GetPackageId()));
}
for (const std::string& input : input_files) {
@@ -1889,6 +1899,7 @@
LinkOptions options;
std::vector<std::string> overlay_arg_list;
std::vector<std::string> extra_java_packages;
+ Maybe<std::string> package_id;
Maybe<std::string> configs;
Maybe<std::string> preferred_density;
Maybe<std::string> product_list;
@@ -1909,6 +1920,10 @@
"Compilation unit to link, using `overlay` semantics.\n"
"The last conflicting resource given takes precedence.",
&overlay_arg_list)
+ .OptionalFlag("--package-id",
+ "Specify the package ID to use for this app. Must be greater or equal to\n"
+ "0x7f and can't be used with --static-lib or --shared-lib.",
+ &package_id)
.OptionalFlag("--java", "Directory in which to generate R.java",
&options.generate_java_class_path)
.OptionalFlag("--proguard", "Output file for generated Proguard rules",
@@ -2062,6 +2077,47 @@
context.SetVerbose(verbose);
}
+ if (shared_lib && static_lib) {
+ context.GetDiagnostics()->Error(DiagMessage()
+ << "only one of --shared-lib and --static-lib can be defined");
+ return 1;
+ }
+
+ if (shared_lib) {
+ options.package_type = PackageType::kSharedLib;
+ context.SetPackageId(0x00);
+ } else if (static_lib) {
+ options.package_type = PackageType::kStaticLib;
+ context.SetPackageId(kAppPackageId);
+ } else {
+ options.package_type = PackageType::kApp;
+ context.SetPackageId(kAppPackageId);
+ }
+
+ if (package_id) {
+ if (options.package_type != PackageType::kApp) {
+ context.GetDiagnostics()->Error(
+ DiagMessage() << "can't specify --package-id when not building a regular app");
+ return 1;
+ }
+
+ const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value());
+ if (!maybe_package_id_int) {
+ context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value()
+ << "' is not a valid integer");
+ return 1;
+ }
+
+ const uint32_t package_id_int = maybe_package_id_int.value();
+ if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) {
+ context.GetDiagnostics()->Error(
+ DiagMessage() << StringPrintf(
+ "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
+ return 1;
+ }
+ context.SetPackageId(static_cast<uint8_t>(package_id_int));
+ }
+
// Populate the set of extra packages for which to generate R.java.
for (std::string& extra_package : extra_java_packages) {
// A given package can actually be a colon separated list of packages.
@@ -2128,18 +2184,6 @@
options.table_splitter_options.preferred_densities.push_back(preferred_density_config.density);
}
- if (shared_lib && static_lib) {
- context.GetDiagnostics()->Error(DiagMessage()
- << "only one of --shared-lib and --static-lib can be defined");
- return 1;
- }
-
- if (shared_lib) {
- options.package_type = PackageType::kSharedLib;
- } else if (static_lib) {
- options.package_type = PackageType::kStaticLib;
- }
-
if (options.package_type != PackageType::kStaticLib && stable_id_file_path) {
if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
&options.stable_id_map)) {