[aapt2] Add --non-updatable-system flag
This adds `updatableSystem="false"` to the root <manifest> tag if no
versionCode is specified (either explicitly or through --version-code).
This attribute makes the APK not updatable (see b/266131956).
Bug: 328302305
Test: atest aapt2_tests
Test: Manually ran `aapt2 link --non-updatable-system` and verified the
resulting APK.
Change-Id: I51cdbcdac7c03de10aac9bc22f5081e12fa142ab
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index dc18b1c..8fe414f 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -335,6 +335,11 @@
"are separated by ',' and the name is separated from the value by '='.\n"
"Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).",
&feature_flags_args_);
+ AddOptionalSwitch("--non-updatable-system",
+ "Mark the app as a non-updatable system app. This inserts\n"
+ "updatableSystem=\"false\" to the root manifest node, overwriting any\n"
+ "existing attribute. This is ignored if the manifest has a versionCode.",
+ &options_.manifest_fixer_options.non_updatable_system);
}
int Action(const std::vector<std::string>& args) override;
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 0b16e2c..b56b4c4 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -487,6 +487,16 @@
}
}
+ if (options_.non_updatable_system) {
+ if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
+ el->RemoveAttribute("", "updatableSystem");
+ el->attributes.push_back(xml::Attribute{"", "updatableSystem", "false"});
+ } else {
+ diag->Note(android::DiagMessage(el->line_number)
+ << "Ignoring --non-updatable-system because the manifest has a versionCode");
+ }
+ }
+
return true;
});
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 42938a4..df0ece6 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -91,6 +91,11 @@
// Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes.
bool no_compile_sdk_metadata = false;
+
+ // Whether to mark the app as a non-updatable system app. This adds `updatableSystem="false"` to
+ // the <manifest> tag. Not used if a version code is set either explicitly in the manifest or
+ // through version_code_default.
+ bool non_updatable_system = false;
};
// Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 6151a8e..3cfdf78 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -677,6 +677,83 @@
EXPECT_THAT(attr->value, StrEq("0x00000002"));
}
+TEST_F(ManifestFixerTest, MarkNonUpdatableSystem) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("false"));
+}
+
+TEST_F(ManifestFixerTest, MarkNonUpdatableSystemOverwritingValue) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android"
+ updatableSystem="true" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("false"));
+}
+
+TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenExplicitVersion) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android"
+ android:versionCode="0x00000001" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, IsNull());
+}
+
+TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenAddedVersion) {
+ ManifestFixerOptions options;
+ options.non_updatable_system = true;
+ options.version_code_default = std::string("0x10000000");
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android" />)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
+ ASSERT_THAT(attr, IsNull());
+
+ attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());