Handle new manifest tag <property>
Bug: 169258655 Test: aapt2_tests Change-Id: Ia1c8e7c38fb882c3ce0aa2913b844cccdc5b8749
This commit is contained in:
@@ -1851,6 +1851,41 @@ class SupportsGlTexture : public ManifestExtractor::Element {
|
||||
}
|
||||
};
|
||||
|
||||
/** Represents <property> elements. **/
|
||||
class Property : public ManifestExtractor::Element {
|
||||
public:
|
||||
Property() = default;
|
||||
std::string name;
|
||||
std::string value;
|
||||
const int* value_int;
|
||||
std::string resource;
|
||||
const int* resource_int;
|
||||
|
||||
void Extract(xml::Element* element) override {
|
||||
name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
|
||||
value = GetAttributeStringDefault(FindAttribute(element, VALUE_ATTR), "");
|
||||
value_int = GetAttributeInteger(FindAttribute(element, VALUE_ATTR));
|
||||
resource = GetAttributeStringDefault(FindAttribute(element, RESOURCE_ATTR), "");
|
||||
resource_int = GetAttributeInteger(FindAttribute(element, RESOURCE_ATTR));
|
||||
}
|
||||
|
||||
void Print(text::Printer* printer) override {
|
||||
printer->Print(StringPrintf("property: name='%s' ", name.data()));
|
||||
if (!value.empty()) {
|
||||
printer->Print(StringPrintf("value='%s' ", value.data()));
|
||||
} else if (value_int) {
|
||||
printer->Print(StringPrintf("value='%d' ", *value_int));
|
||||
} else {
|
||||
if (!resource.empty()) {
|
||||
printer->Print(StringPrintf("resource='%s' ", resource.data()));
|
||||
} else if (resource_int) {
|
||||
printer->Print(StringPrintf("resource='%d' ", *resource_int));
|
||||
}
|
||||
}
|
||||
printer->Print("\n");
|
||||
}
|
||||
};
|
||||
|
||||
/** Recursively prints the extracted badging element. */
|
||||
static void Print(ManifestExtractor::Element* el, text::Printer* printer) {
|
||||
el->Print(printer);
|
||||
@@ -2291,6 +2326,7 @@ T* ElementCast(ManifestExtractor::Element* element) {
|
||||
{"overlay", std::is_base_of<Overlay, T>::value},
|
||||
{"package-verifier", std::is_base_of<PackageVerifier, T>::value},
|
||||
{"permission", std::is_base_of<Permission, T>::value},
|
||||
{"property", std::is_base_of<Property, T>::value},
|
||||
{"provider", std::is_base_of<Provider, T>::value},
|
||||
{"receiver", std::is_base_of<Receiver, T>::value},
|
||||
{"required-feature", std::is_base_of<RequiredFeature, T>::value},
|
||||
@@ -2344,6 +2380,7 @@ std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
|
||||
{"overlay", &CreateType<Overlay>},
|
||||
{"package-verifier", &CreateType<PackageVerifier>},
|
||||
{"permission", &CreateType<Permission>},
|
||||
{"property", &CreateType<Property>},
|
||||
{"provider", &CreateType<Provider>},
|
||||
{"receiver", &CreateType<Receiver>},
|
||||
{"required-feature", &CreateType<RequiredFeature>},
|
||||
|
||||
@@ -112,6 +112,27 @@ static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std
|
||||
};
|
||||
}
|
||||
|
||||
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 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
|
||||
// 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 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
|
||||
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 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
|
||||
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);
|
||||
|
||||
@@ -886,4 +886,78 @@ TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user