Handle new manifest tag <property>
Bug: 169258655
Test: aapt2_tests
Change-Id: Ia1c8e7c38fb882c3ce0aa2913b844cccdc5b8749
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 3d8c25e..fd3a4c0 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -112,6 +112,27 @@
};
}
+static xml::XmlNodeAction::ActionFuncWithDiag RequiredOneAndroidAttribute(
+ const std::string& attrName1, const std::string& attrName2) {
+ return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
+ xml::Attribute* attr1 = el->FindAttribute(xml::kSchemaAndroid, attrName1);
+ xml::Attribute* attr2 = el->FindAttribute(xml::kSchemaAndroid, attrName2);
+ if (attr1 == nullptr && attr2 == nullptr) {
+ diag->Error(DiagMessage(el->line_number)
+ << "<" << el->name << "> is missing required attribute 'android:" << attrName1
+ << "' or 'android:" << attrName2 << "'");
+ return false;
+ }
+ if (attr1 != nullptr && attr2 != nullptr) {
+ diag->Error(DiagMessage(el->line_number)
+ << "<" << el->name << "> can only specify one of attribute 'android:" << attrName1
+ << "' or 'android:" << attrName2 << "'");
+ return false;
+ }
+ return true;
+ };
+}
+
static bool AutoGenerateIsFeatureSplit(xml::Element* el, SourcePathDiagnostics* diag) {
constexpr const char* kFeatureSplit = "featureSplit";
constexpr const char* kIsFeatureSplit = "isFeatureSplit";
@@ -282,6 +303,10 @@
// Common <meta-data> actions.
xml::XmlNodeAction meta_data_action;
+ // Common <property> actions.
+ xml::XmlNodeAction property_action;
+ property_action.Action(RequiredOneAndroidAttribute("resource", "value"));
+
// Common <uses-feature> actions.
xml::XmlNodeAction uses_feature_action;
uses_feature_action.Action(VerifyUsesFeature);
@@ -292,6 +317,7 @@
component_action["intent-filter"] = intent_filter_action;
component_action["preferred"] = intent_filter_action;
component_action["meta-data"] = meta_data_action;
+ component_action["property"] = property_action;
// Manifest actions.
xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
@@ -427,6 +453,7 @@
application_action["uses-native-library"].Action(RequiredNameIsNotEmpty);
application_action["library"].Action(RequiredNameIsNotEmpty);
application_action["profileable"];
+ application_action["property"] = property_action;
xml::XmlNodeAction& static_library_action = application_action["static-library"];
static_library_action.Action(RequiredNameIsJavaPackage);
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 0791805..781ff7b 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -886,4 +886,78 @@
EXPECT_THAT(Verify(input), NotNull());
}
+TEST_F(ManifestFixerTest, ApplicationPropertyAttributeRequired) {
+ std::string input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <property android:name="" />
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), IsNull());
+}
+
+TEST_F(ManifestFixerTest, ApplicationPropertyOnlyOneAttributeDefined) {
+ std::string input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <property android:name="" android:value="" android:resource="" />
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), IsNull());
+
+ input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <property android:name="" android:resource="" />
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), NotNull());
+
+ input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <property android:name="" android:value="" />
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), NotNull());
+}
+
+TEST_F(ManifestFixerTest, ComponentPropertyOnlyOneAttributeDefined) {
+ std::string input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <activity android:name=".MyActivity">
+ <property android:name="" android:value="" android:resource="" />
+ </activity>
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), IsNull());
+
+ input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <activity android:name=".MyActivity">
+ <property android:name="" android:value="" />
+ </activity>
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), NotNull());
+
+ input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ <activity android:name=".MyActivity">
+ <property android:name="" android:resource="" />
+ </activity>
+ </application>
+ </manifest>)";
+ EXPECT_THAT(Verify(input), NotNull());
+}
} // namespace aapt