summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SafetyCenter/Config/Android.bp18
-rw-r--r--SafetyCenter/Config/java/com/android/safetycenter/config/Parser.java361
-rw-r--r--SafetyCenter/Config/tests/Android.bp38
-rw-r--r--SafetyCenter/Config/tests/AndroidManifest.xml30
-rw-r--r--SafetyCenter/Config/tests/AndroidTest.xml36
-rw-r--r--SafetyCenter/Config/tests/SafetyCenterConfigTestResources/Android.bp26
-rw-r--r--SafetyCenter/Config/tests/SafetyCenterConfigTestResources/AndroidManifest.xml20
-rw-r--r--SafetyCenter/Config/tests/SafetyCenterConfigTestResources/res/values/strings.xml20
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceBaseTest.kt56
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceDuplicateKey.kt57
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceInvalidProfile.kt44
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoId.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoIntent.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoPackage.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoProfile.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoSummary.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoTitle.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceFileCorrupted.kt27
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceDuplicateKey.kt47
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceNoId.kt38
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithBroadcast.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithIntent.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithLogging.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithPackage.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithProfile.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSearch.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSummary.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithTitle.kt40
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceDuplicateKey.kt50
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceInvalidType.kt39
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceNoType.kt38
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourcesGroupDuplicateId.kt50
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceInvalid.kt39
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceMissing.kt39
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetyCenterConfigMissing.kt29
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigEmpty.kt33
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigMissing.kt31
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupDuplicateId.kt47
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupEmpty.kt36
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoId.kt38
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoSummary.kt38
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoTitle.kt38
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceDuplicateKey.kt55
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceInvalidProfile.kt43
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoId.kt42
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoIntent.kt42
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoProfile.kt42
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoSummary.kt42
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoTitle.kt42
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithBroadcast.kt44
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithLogging.kt44
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithPackage.kt44
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupDuplicateId.kt53
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoId.kt41
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoTitle.kt41
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceValid.kt118
56 files changed, 2634 insertions, 0 deletions
diff --git a/SafetyCenter/Config/Android.bp b/SafetyCenter/Config/Android.bp
index 18db2de53..097231340 100644
--- a/SafetyCenter/Config/Android.bp
+++ b/SafetyCenter/Config/Android.bp
@@ -23,3 +23,21 @@ xsd_config {
package_name: "com.android.safetycenter.config.parser",
boolean_getter: true,
}
+
+java_library {
+ name: "safety-center-config",
+ srcs: [
+ "java/**/*.java",
+ ":safety-center-config-parser",
+ ],
+ libs: [
+ "framework-annotations-lib",
+ ],
+ apex_available: [
+ "com.android.permission",
+ "test_com.android.permission",
+ ],
+ installable: false,
+ min_sdk_version: "30",
+ sdk_version: "module_current",
+}
diff --git a/SafetyCenter/Config/java/com/android/safetycenter/config/Parser.java b/SafetyCenter/Config/java/com/android/safetycenter/config/Parser.java
new file mode 100644
index 000000000..47a0c2129
--- /dev/null
+++ b/SafetyCenter/Config/java/com/android/safetycenter/config/Parser.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources;
+
+import com.android.safetycenter.config.parser.SafetyCenterConfig;
+import com.android.safetycenter.config.parser.SafetySource;
+import com.android.safetycenter.config.parser.SafetySourcesConfig;
+import com.android.safetycenter.config.parser.SafetySourcesGroup;
+import com.android.safetycenter.config.parser.StaticSafetySourcesGroup;
+import com.android.safetycenter.config.parser.XmlParser;
+
+import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/** Utility class to parse and validate a Safety Center Config */
+public final class Parser {
+ /** Static safety source */
+ public static final int SAFETY_SOURCE_TYPE_STATIC = 1;
+
+ /** Dynamic safety source */
+ public static final int SAFETY_SOURCE_TYPE_DYNAMIC = 2;
+
+ /** Internal safety source */
+ public static final int SAFETY_SOURCE_TYPE_INTERNAL = 3;
+
+ /** All possible safety source types */
+ @IntDef(prefix = {"SAFETY_SOURCE_TYPE_"}, value = {
+ SAFETY_SOURCE_TYPE_STATIC,
+ SAFETY_SOURCE_TYPE_DYNAMIC,
+ SAFETY_SOURCE_TYPE_INTERNAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SafetySourceType {
+ }
+
+ /**
+ * Even when the active user has managed profiles, the safety source will be displayed as a
+ * single entry for the primary profile.
+ */
+ public static final int PROFILE_PRIMARY = 1;
+
+ /**
+ * When the user has managed profiles, the safety source will be displayed as multiple entries
+ * one for each profile.
+ */
+ public static final int PROFILE_ALL = 2;
+
+ /** All possible profile configurations for a safety source */
+ @IntDef(prefix = {"PROFILE_"}, value = {
+ PROFILE_PRIMARY,
+ PROFILE_ALL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Profile {
+ }
+
+ private static final class SourceId {
+ @Nullable
+ private final String mPackageName;
+ @NonNull
+ private final String mId;
+
+ private SourceId(@Nullable String packageName, @NonNull String id) {
+ this.mPackageName = packageName;
+ this.mId = id;
+ }
+
+ @NonNull
+ private static SourceId of(@Nullable String packageName, @NonNull String id) {
+ return new SourceId(packageName, id);
+ }
+
+ @Override
+ public String toString() {
+ return "SourceId{"
+ + "mPackageName='"
+ + (mPackageName == null ? "null" : mPackageName)
+ + '\''
+ + ", mId='"
+ + mId
+ + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SourceId)) return false;
+ SourceId key = (SourceId) o;
+ return Objects.equals(this.mPackageName, key.mPackageName)
+ && Objects.equals(this.mId, key.mId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mId);
+ }
+ }
+
+ /** Thrown when there is an error parsing the Safety Center Config */
+ public static final class ParseException extends Exception {
+ public ParseException(String message) {
+ super(message);
+ }
+
+ public ParseException(String message, Throwable ex) {
+ super(message, ex);
+ }
+ }
+
+ /**
+ * Parses and validates the given raw XML resource into a {@link SafetyCenterConfig} object.
+ *
+ * @param in the name of the raw XML resource in the package that contains the
+ * Safety Center
+ * Config
+ * @param resourcePkgName the name of the package that contains the Safety Center Config
+ * @param resources the {@link Resources} retrieved from the package that contains the
+ * Safety Center Config
+ */
+ @Nullable
+ public static SafetyCenterConfig parse(@NonNull InputStream in, @NonNull String resourcePkgName,
+ @NonNull Resources resources) throws ParseException {
+ if (in == null) {
+ throw new ParseException("Parameter in must be defined");
+ }
+ if (resourcePkgName == null || resourcePkgName.isEmpty()) {
+ throw new ParseException("Resource package name must be defined");
+ }
+ if (resources == null) {
+ throw new ParseException("Resources must be defined");
+ }
+ SafetyCenterConfig safetyCenterConfig;
+ try {
+ safetyCenterConfig = XmlParser.read(in);
+ } catch (Exception e) {
+ throw new ParseException("Exception while reading XML", e);
+ }
+ validate(safetyCenterConfig, resourcePkgName, resources);
+ return safetyCenterConfig;
+ }
+
+ private static void validate(@Nullable SafetyCenterConfig safetyCenterConfig,
+ @NonNull String resourcePkgName, @NonNull Resources resources) throws ParseException {
+ if (safetyCenterConfig == null) {
+ throw new ParseException("Element safety-center-config missing");
+ }
+ validate(safetyCenterConfig.getSafetySourcesConfig(), resourcePkgName, resources);
+ }
+
+ private static void validate(@Nullable SafetySourcesConfig safetySourcesConfig,
+ @NonNull String resourcePkgName, @NonNull Resources resources) throws ParseException {
+ if (safetySourcesConfig == null) {
+ throw new ParseException("Element safety-sources-config missing");
+ }
+ if ((safetySourcesConfig.getSafetySourcesGroup() == null
+ || safetySourcesConfig.getSafetySourcesGroup().isEmpty()) && (
+ safetySourcesConfig.getStaticSafetySourcesGroup() == null
+ || safetySourcesConfig.getStaticSafetySourcesGroup().isEmpty())) {
+ throw new ParseException("Element safety-sources-config empty");
+ }
+ Set<String> groupIds = new HashSet<>();
+ Set<SourceId> sourceIds = new HashSet<>();
+ List<SafetySourcesGroup> safetySourcesGroups = safetySourcesConfig.getSafetySourcesGroup();
+ if (safetySourcesGroups != null) {
+ for (SafetySourcesGroup safetySourcesGroup : safetySourcesGroups) {
+ validate(safetySourcesGroup, groupIds, sourceIds, resourcePkgName, resources);
+ }
+ }
+ List<StaticSafetySourcesGroup> staticSafetySourcesGroups =
+ safetySourcesConfig.getStaticSafetySourcesGroup();
+ if (staticSafetySourcesGroups != null) {
+ for (StaticSafetySourcesGroup staticSafetySourcesGroup : staticSafetySourcesGroups) {
+ validate(staticSafetySourcesGroup, groupIds, sourceIds, resourcePkgName, resources);
+ }
+ }
+ }
+
+ private static void validate(@Nullable SafetySourcesGroup safetySourcesGroup,
+ @NonNull Set<String> groupIds, @NonNull Set<SourceId> sourceIds,
+ @NonNull String resourcePkgName, @NonNull Resources resources) throws ParseException {
+ if (safetySourcesGroup == null) {
+ throw new ParseException("Element safety-sources-group invalid");
+ }
+ validateGroupId(safetySourcesGroup.getId(), groupIds, "safety-sources-group");
+ validateReference(safetySourcesGroup.getTitle(), "safety-sources-group.title", true, false,
+ resourcePkgName, resources);
+ validateReference(safetySourcesGroup.getSummary(), "safety-sources-group.summary", true,
+ false, resourcePkgName, resources);
+ List<SafetySource> safetySources = safetySourcesGroup.getSafetySource();
+ if (safetySources == null || safetySources.isEmpty()) {
+ throw new ParseException("Element safety-sources-group empty");
+ }
+ for (SafetySource safetySource : safetySources) {
+ validate(safetySource, sourceIds, resourcePkgName, resources, "safety-source");
+ }
+ }
+
+ private static void validate(@Nullable StaticSafetySourcesGroup staticSafetySourcesGroup,
+ @NonNull Set<String> groupIds, @NonNull Set<SourceId> sourceIds,
+ @NonNull String resourcePkgName, @NonNull Resources resources) throws ParseException {
+ if (staticSafetySourcesGroup == null) {
+ throw new ParseException("Element static-safety-sources-group invalid");
+ }
+ validateGroupId(staticSafetySourcesGroup.getId(), groupIds, "static-safety-sources-group");
+ validateReference(staticSafetySourcesGroup.getTitle(), "static-safety-sources-group.title",
+ true, false, resourcePkgName, resources);
+ List<SafetySource> staticSafetySources = staticSafetySourcesGroup.getStaticSafetySource();
+ if (staticSafetySources == null || staticSafetySources.isEmpty()) {
+ throw new ParseException("Element static-safety-sources-group empty");
+ }
+ for (SafetySource staticSafetySource : staticSafetySources) {
+ if (staticSafetySource.getType() != SAFETY_SOURCE_TYPE_STATIC) {
+ throw new ParseException(
+ String.format("Invalid type %d in static-safety-sources-group",
+ staticSafetySource.getType()));
+ }
+ validate(staticSafetySource, sourceIds, resourcePkgName, resources,
+ "static-safety-source");
+ }
+ }
+
+ private static void validate(@Nullable SafetySource safetySource,
+ @NonNull Set<SourceId> sourceIds, @NonNull String resourcePkgName,
+ @NonNull Resources resources, @NonNull String name) throws ParseException {
+ if (safetySource == null) {
+ throw new ParseException(String.format("Element %s invalid", name));
+ }
+ validateType(safetySource.getType(), name);
+ boolean isStatic = safetySource.getType() == SAFETY_SOURCE_TYPE_STATIC;
+ boolean isDynamic = safetySource.getType() == SAFETY_SOURCE_TYPE_DYNAMIC;
+ boolean isInternal = safetySource.getType() == SAFETY_SOURCE_TYPE_INTERNAL;
+ validateSourceId(safetySource.getId(), safetySource.getPackageName(), isDynamic,
+ isStatic || isInternal, sourceIds, name);
+ validateReference(safetySource.getTitle(), name + ".title", isDynamic || isStatic,
+ isInternal, resourcePkgName, resources);
+ validateReference(safetySource.getSummary(), name + ".summary", isDynamic || isStatic,
+ isInternal, resourcePkgName, resources);
+ validateString(safetySource.getIntentAction(), name + ".intentAction",
+ isDynamic || isStatic, isInternal);
+ validateProfile(safetySource.getProfile(), name, isDynamic || isStatic,
+ isInternal);
+ validateReference(safetySource.getSearchTerms(), name + ".searchTerms", false, isInternal,
+ resourcePkgName, resources);
+ validateString(safetySource.getBroadcastReceiverClassName(),
+ name + ".broadcastReceiverClassName", false, isStatic || isInternal);
+ if (safetySource.isDisallowLogging() && (isStatic || isInternal)) {
+ throw new ParseException(
+ String.format("Prohibited attribute %s.disallowLogging present", name));
+ }
+ }
+
+ private static void validateGroupId(@Nullable String id, @NonNull Set<String> groupIds,
+ @NonNull String name) throws ParseException {
+ validateString(id, name + ".id", true, false);
+
+ if (groupIds.contains(id)) {
+ throw new ParseException(String.format(
+ "Duplicate id %s among safety-sources-groups and static-safety-sources-groups",
+ id));
+ }
+ groupIds.add(id);
+ }
+
+ private static void validateType(int type, @NonNull String name) throws ParseException {
+ if (type != SAFETY_SOURCE_TYPE_STATIC
+ && type != SAFETY_SOURCE_TYPE_DYNAMIC
+ && type != SAFETY_SOURCE_TYPE_INTERNAL) {
+ throw new ParseException(
+ String.format("Required attribute %s.type missing or invalid", name));
+ }
+ }
+
+ private static void validateProfile(int profile, @NonNull String name, boolean required,
+ boolean prohibited) throws ParseException {
+ if (profile != 0
+ && profile != PROFILE_PRIMARY
+ && profile != PROFILE_ALL) {
+ throw new ParseException(String.format("Attribute %s.profile invalid", name));
+ }
+ if (required && profile == 0) {
+ throw new ParseException(
+ String.format("Required attribute %s.profile missing or invalid", name));
+ }
+ if (prohibited && profile != 0) {
+ throw new ParseException(
+ String.format("Prohibited attribute %s.profile present", name));
+ }
+ }
+
+ private static void validateSourceId(@Nullable String id, @Nullable String packageName,
+ boolean packageNameRequired, boolean packageNameProhibited,
+ @NonNull Set<SourceId> sourceIds, @NonNull String name) throws ParseException {
+ validateString(id, name + ".id", true, false);
+ validateString(packageName, name + ".packageName", packageNameRequired,
+ packageNameProhibited);
+ SourceId key = SourceId.of(packageName, id);
+ if (sourceIds.contains(key)) {
+ throw new ParseException(
+ String.format("Duplicate id %s %s",
+ id,
+ packageNameRequired
+ ? "for package " + packageName
+ : "among static and internal safety sources"));
+ }
+ sourceIds.add(key);
+ }
+
+ private static void validateString(@Nullable String s, @NonNull String name, boolean required,
+ boolean prohibited) throws ParseException {
+ if (s == null || s.isEmpty()) {
+ if (required) {
+ throw new ParseException(String.format("Required attribute %s missing", name));
+ }
+ } else {
+ if (prohibited) {
+ throw new ParseException(String.format("Prohibited attribute %s present", name));
+ }
+ }
+ }
+
+ private static void validateReference(@Nullable String s, @NonNull String name,
+ boolean required, boolean prohibited, @NonNull String resourcePkgName,
+ @NonNull Resources resources) throws ParseException {
+ validateString(s, name, required, prohibited);
+ if (s != null) {
+ if (s.startsWith("@string/")) {
+ if (resources.getIdentifier(s.substring(1), null, resourcePkgName) == 0) {
+ throw new ParseException(String.format("Reference %s in %s missing", s, name));
+ }
+ } else {
+ throw new ParseException(
+ String.format("String %s in %s is not a reference", s, name));
+ }
+ }
+ }
+}
diff --git a/SafetyCenter/Config/tests/Android.bp b/SafetyCenter/Config/tests/Android.bp
new file mode 100644
index 000000000..71c9544a0
--- /dev/null
+++ b/SafetyCenter/Config/tests/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "SafetyCenterConfigTests",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ min_sdk_version: "30",
+ srcs: [
+ "java/**/*.kt",
+ ],
+ static_libs: [
+ "safety-center-config",
+ "compatibility-device-util-axt",
+ ],
+ data: [
+ ":SafetyCenterConfigTestResources",
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/SafetyCenter/Config/tests/AndroidManifest.xml b/SafetyCenter/Config/tests/AndroidManifest.xml
new file mode 100644
index 000000000..5ccda9508
--- /dev/null
+++ b/SafetyCenter/Config/tests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.safetycenter.tests.config.safetycenterconfig">
+
+ <application android:label="Safety Center Config Tests">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.safetycenter.tests.config.safetycenterconfig"
+ android:label="Tests for the Safety Center Config library" />
+</manifest>
diff --git a/SafetyCenter/Config/tests/AndroidTest.xml b/SafetyCenter/Config/tests/AndroidTest.xml
new file mode 100644
index 000000000..1cd242024
--- /dev/null
+++ b/SafetyCenter/Config/tests/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<configuration description="Runs unit tests for the Safety Center Config library.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+ <option name="test-tag" value="SafetyCenterConfigTests" />
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+ <!-- Install test and resources -->
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="SafetyCenterConfigTests.apk" />
+ <option name="test-file-name" value="SafetyCenterConfigTestResources.apk" />
+ <option name="cleanup-apks" value="true" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.safetycenter.tests.config.safetycenterconfig" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
diff --git a/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/Android.bp b/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/Android.bp
new file mode 100644
index 000000000..700197666
--- /dev/null
+++ b/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "SafetyCenterConfigTestResources",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ min_sdk_version: "30",
+}
diff --git a/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/AndroidManifest.xml b/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/AndroidManifest.xml
new file mode 100644
index 000000000..8c22c24b0
--- /dev/null
+++ b/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.safetycenter.tests.config.safetycenterconfigtestresources">
+ <application/>
+</manifest>
diff --git a/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/res/values/strings.xml b/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/res/values/strings.xml
new file mode 100644
index 000000000..8ba7f04a8
--- /dev/null
+++ b/SafetyCenter/Config/tests/SafetyCenterConfigTestResources/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Test reference -->
+ <string name="reference" translatable="false">Reference</string>
+</resources>
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceBaseTest.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceBaseTest.kt
new file mode 100644
index 000000000..de4fb8754
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceBaseTest.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import android.content.Context
+import android.content.res.Resources
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import java.io.InputStream
+
+abstract class ResourceBaseTest(
+ val inputString: String,
+ val message: String? = null
+) {
+ private val context: Context = getApplicationContext()
+
+ @Test
+ fun validate() {
+ val inputStream: InputStream = inputString.byteInputStream()
+ val resources: Resources = context.createPackageContext(RESOURCE_PKG, 0).resources
+ if (message != null) {
+ val thrown = assertThrows(Parser.ParseException::class.java) {
+ Parser.parse(
+ inputStream,
+ RESOURCE_PKG,
+ resources
+ )
+ }
+ assertThat(thrown).hasMessageThat().isEqualTo(message)
+ } else {
+ assertNotNull(Parser.parse(inputStream, RESOURCE_PKG, resources))
+ }
+ }
+
+ companion object {
+ const val RESOURCE_PKG =
+ "com.android.safetycenter.tests.config.safetycenterconfigtestresources"
+ }
+}
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceDuplicateKey.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceDuplicateKey.kt
new file mode 100644
index 000000000..3ee32e6da
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceDuplicateKey.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceDuplicateKey : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id1"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="id2"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id for package package"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceInvalidProfile.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceInvalidProfile.kt
new file mode 100644
index 000000000..994195023
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceInvalidProfile.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceInvalidProfile : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="9"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Attribute safety-source.profile invalid"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoId.kt
new file mode 100644
index 000000000..d2d06d4eb
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoId.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceNoId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.id missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoIntent.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoIntent.kt
new file mode 100644
index 000000000..a55f28e5c
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoIntent.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceNoIntent : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.intentAction missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoPackage.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoPackage.kt
new file mode 100644
index 000000000..d4569ae58
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoPackage.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceNoPackage : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.packageName missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoProfile.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoProfile.kt
new file mode 100644
index 000000000..1d1801055
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoProfile.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceNoProfile : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.profile missing or invalid"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoSummary.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoSummary.kt
new file mode 100644
index 000000000..7c5de72ad
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoSummary.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceNoSummary : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ title="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.summary missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoTitle.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoTitle.kt
new file mode 100644
index 000000000..443ece0b7
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceDynamicSafetySourceNoTitle.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceDynamicSafetySourceNoTitle : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="id"
+ packageName="package"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.title missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceFileCorrupted.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceFileCorrupted.kt
new file mode 100644
index 000000000..53f896770
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceFileCorrupted.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceFileCorrupted : ResourceBaseTest(
+ """
+ """,
+ "Exception while reading XML"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceDuplicateKey.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceDuplicateKey.kt
new file mode 100644
index 000000000..2dc4b8438
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceDuplicateKey.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceDuplicateKey : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id1"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="id2"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id among static and internal safety sources"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceNoId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceNoId.kt
new file mode 100644
index 000000000..04afdac03
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceNoId.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceNoId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.id missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithBroadcast.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithBroadcast.kt
new file mode 100644
index 000000000..64d510a6a
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithBroadcast.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithBroadcast : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ broadcastReceiverClassName="broadcast"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.broadcastReceiverClassName present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithIntent.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithIntent.kt
new file mode 100644
index 000000000..f7f30ea64
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithIntent.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithIntent : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ intentAction="intent"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.intentAction present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithLogging.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithLogging.kt
new file mode 100644
index 000000000..2d2d7304f
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithLogging.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithLogging : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ disallowLogging="true"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.disallowLogging present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithPackage.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithPackage.kt
new file mode 100644
index 000000000..302de4024
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithPackage.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithPackage : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ packageName="package"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.packageName present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithProfile.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithProfile.kt
new file mode 100644
index 000000000..f614c7ed6
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithProfile.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithProfile : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.profile present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSearch.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSearch.kt
new file mode 100644
index 000000000..2eefc1bb8
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSearch.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithSearch : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ searchTerms="@string/reference"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.searchTerms present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSummary.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSummary.kt
new file mode 100644
index 000000000..d2a63d88c
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithSummary.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithSummary : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ summary="@string/reference"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.summary present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithTitle.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithTitle.kt
new file mode 100644
index 000000000..b9f50096f
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceInternalSafetySourceWithTitle.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceInternalSafetySourceWithTitle : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"
+ title="@string/reference"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.title present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceDuplicateKey.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceDuplicateKey.kt
new file mode 100644
index 000000000..b609d4f39
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceDuplicateKey.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceMixedSafetySourceDuplicateKey : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id1"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ <static-safety-sources-group
+ id="id2"
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </static-safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id among static and internal safety sources"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceInvalidType.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceInvalidType.kt
new file mode 100644
index 000000000..6ba7392fe
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceInvalidType.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceMixedSafetySourceInvalidType : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="9"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.type missing or invalid"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceNoType.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceNoType.kt
new file mode 100644
index 000000000..d15d5cf6a
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourceNoType.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceMixedSafetySourceNoType : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.type missing or invalid"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourcesGroupDuplicateId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourcesGroupDuplicateId.kt
new file mode 100644
index 000000000..b05555f7d
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceMixedSafetySourcesGroupDuplicateId.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceMixedSafetySourcesGroupDuplicateId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id1"/>
+ </safety-sources-group>
+ <static-safety-sources-group
+ id="id"
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="id2"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </static-safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id among safety-sources-groups and static-safety-sources-groups"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceInvalid.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceInvalid.kt
new file mode 100644
index 000000000..d0cf593fd
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceInvalid.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceReferenceInvalid : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="title"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "String title in safety-sources-group.title is not a reference"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceMissing.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceMissing.kt
new file mode 100644
index 000000000..33986d433
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceReferenceMissing.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceReferenceMissing : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference2">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Reference @string/reference2 in safety-sources-group.summary missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetyCenterConfigMissing.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetyCenterConfigMissing.kt
new file mode 100644
index 000000000..dfd10ee13
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetyCenterConfigMissing.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetyCenterConfigMissing : ResourceBaseTest(
+ """
+<other-root>
+</other-root>
+ """,
+ "Element safety-center-config missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigEmpty.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigEmpty.kt
new file mode 100644
index 000000000..f2c5863eb
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigEmpty.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesConfigEmpty : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <other-element>
+ </other-element>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Element safety-sources-config empty"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigMissing.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigMissing.kt
new file mode 100644
index 000000000..a167091f7
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesConfigMissing.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesConfigMissing : ResourceBaseTest(
+ """
+<safety-center-config>
+ <other-internal-config>
+ </other-internal-config>
+</safety-center-config>
+ """,
+ "Element safety-sources-config missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupDuplicateId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupDuplicateId.kt
new file mode 100644
index 000000000..ca70f23ce
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupDuplicateId.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesGroupDuplicateId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id1"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id2"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id among safety-sources-groups and static-safety-sources-groups"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupEmpty.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupEmpty.kt
new file mode 100644
index 000000000..0495be17c
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupEmpty.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesGroupEmpty : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Element safety-sources-group empty"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoId.kt
new file mode 100644
index 000000000..0bb414e2a
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoId.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesGroupNoId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-sources-group.id missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoSummary.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoSummary.kt
new file mode 100644
index 000000000..690ad07bf
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoSummary.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesGroupNoSummary : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-sources-group.summary missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoTitle.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoTitle.kt
new file mode 100644
index 000000000..1d9d24b57
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceSafetySourcesGroupNoTitle.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceSafetySourcesGroupNoTitle : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="id"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-sources-group.title missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceDuplicateKey.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceDuplicateKey.kt
new file mode 100644
index 000000000..7113019d0
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceDuplicateKey.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceDuplicateKey : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id1"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="id2"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id among static and internal safety sources"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceInvalidProfile.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceInvalidProfile.kt
new file mode 100644
index 000000000..0fe44c959
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceInvalidProfile.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceInvalidProfile : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="9"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Attribute safety-source.profile invalid"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoId.kt
new file mode 100644
index 000000000..69b070014
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoId.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceNoId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.id missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoIntent.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoIntent.kt
new file mode 100644
index 000000000..0a0d31b49
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoIntent.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceNoIntent : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.intentAction missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoProfile.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoProfile.kt
new file mode 100644
index 000000000..ac300c8f4
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoProfile.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceNoProfile : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.profile missing or invalid"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoSummary.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoSummary.kt
new file mode 100644
index 000000000..711a1a6a2
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoSummary.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceNoSummary : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.summary missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoTitle.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoTitle.kt
new file mode 100644
index 000000000..86bf20d98
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceNoTitle.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceNoTitle : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute safety-source.title missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithBroadcast.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithBroadcast.kt
new file mode 100644
index 000000000..e5ce35a6c
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithBroadcast.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceWithBroadcast : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"
+ broadcastReceiverClassName="broadcast"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.broadcastReceiverClassName present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithLogging.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithLogging.kt
new file mode 100644
index 000000000..e0e346f18
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithLogging.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceWithLogging : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"
+ disallowLogging="true"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.disallowLogging present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithPackage.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithPackage.kt
new file mode 100644
index 000000000..6bd394bfd
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourceWithPackage.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourceWithPackage : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"
+ packageName="package"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Prohibited attribute safety-source.packageName present"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupDuplicateId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupDuplicateId.kt
new file mode 100644
index 000000000..e7bc1a31c
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupDuplicateId.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourcesGroupDuplicateId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <static-safety-sources-group
+ id="id"
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="id1"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </static-safety-sources-group>
+ <static-safety-sources-group
+ id="id"
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="id2"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </static-safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Duplicate id id among safety-sources-groups and static-safety-sources-groups"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoId.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoId.kt
new file mode 100644
index 000000000..ac716648f
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoId.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourcesGroupNoId : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <static-safety-sources-group
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </static-safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute static-safety-sources-group.id missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoTitle.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoTitle.kt
new file mode 100644
index 000000000..2422e05ee
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceStaticSafetySourcesGroupNoTitle.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceStaticSafetySourcesGroupNoTitle : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <static-safety-sources-group
+ id="id">
+ <static-safety-source
+ type="1"
+ id="id"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ </static-safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """,
+ "Required attribute static-safety-sources-group.title missing"
+)
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceValid.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceValid.kt
new file mode 100644
index 000000000..f397ed098
--- /dev/null
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ResourceValid.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.safetycenter.config
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ResourceValid : ResourceBaseTest(
+ """
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="security"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="2"
+ id="app_security"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="2"
+ searchTerms="@string/reference"
+ broadcastReceiverClassName="broadcast"
+ disallowLogging="true"/>
+ <safety-source
+ type="3"
+ id="device_security"/>
+ <safety-source
+ type="1"
+ id="lockscreen"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"
+ searchTerms="@string/reference"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="privacy"
+ title="@string/reference"
+ summary="@string/reference">
+ <safety-source
+ type="3"
+ id="privacy_dashboard"/>
+ <safety-source
+ type="1"
+ id="permissions"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="2"/>
+ <safety-source
+ type="2"
+ id="privacy_controls"
+ packageName="package"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="2"/>
+ </safety-sources-group>
+ <static-safety-sources-group
+ id="oem"
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="oem_setting_1"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ <static-safety-source
+ type="1"
+ id="oem_setting_2"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"
+ searchTerms="@string/reference"/>
+ </static-safety-sources-group>
+ <static-safety-sources-group
+ id="advanced"
+ title="@string/reference">
+ <static-safety-source
+ type="1"
+ id="advanced_security"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"/>
+ <static-safety-source
+ type="1"
+ id="advanced_privacy"
+ title="@string/reference"
+ summary="@string/reference"
+ intentAction="intent"
+ profile="1"
+ searchTerms="@string/reference"/>
+ </static-safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
+ """
+)