summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jan Tomljanovic <jtomljanovic@google.com> 2022-11-10 14:26:36 +0000
committer Jan Tomljanovic <jtomljanovic@google.com> 2022-11-17 13:40:54 +0000
commit51b5f99c35f8378564d3a200b86d5919d2eb6806 (patch)
treed4a899bcee9d86f3bd5950b5c816f228c8502d73
parent3f25a57349eaba775bf81dbc50bdb02fa7635499 (diff)
Add deduplication group attribute to the SafetyCenterConfig.
Deduplication groups allow sources which are part of the same group to deduplicate their issues. Bug: 255334450 Test: atest CtsSafetyCenterTestCases SafetyCenterConfigTests Change-Id: I49dad1adabf4bc639a0a298561918e2fb5962244
-rw-r--r--SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java13
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt7
-rw-r--r--SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt20
-rw-r--r--SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_deduplication_groups.xml32
-rw-r--r--SafetyCenter/Config/tests/res/raw-v34/config_valid.xml10
-rw-r--r--SafetyCenter/Config/tests/res/values/strings.xml2
-rw-r--r--framework-s/api/system-current.txt2
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceIssue.java5
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySource.java56
-rw-r--r--framework-s/java/android/safetycenter/config/safety_center_config.xsd2
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt142
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt19
12 files changed, 294 insertions, 16 deletions
diff --git a/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java b/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java
index 5c8da1ed6..adb7260ba 100644
--- a/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java
+++ b/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java
@@ -74,6 +74,7 @@ public final class SafetyCenterConfigParser {
private static final String ATTR_SAFETY_SOURCE_REFRESH_ON_PAGE_OPEN_ALLOWED =
"refreshOnPageOpenAllowed";
private static final String ATTR_SAFETY_SOURCE_NOTIFICATIONS_ALLOWED = "notificationsAllowed";
+ private static final String ATTR_SAFETY_SOURCE_DEDUPLICATION_GROUP = "deduplicationGroup";
private static final String ENUM_STATELESS_ICON_TYPE_NONE = "none";
private static final String ENUM_STATELESS_ICON_TYPE_PRIVACY = "privacy";
private static final String ENUM_PROFILE_PRIMARY = "primary_profile_only";
@@ -336,6 +337,18 @@ public final class SafetyCenterConfigParser {
throw attributeUnexpected(name, parser.getAttributeName(i));
}
break;
+ case ATTR_SAFETY_SOURCE_DEDUPLICATION_GROUP:
+ if (SdkLevel.isAtLeastU()) {
+ builder.setDeduplicationGroup(
+ parseStringResourceValue(
+ parser.getAttributeValue(i),
+ name,
+ parser.getAttributeName(i),
+ resources));
+ } else {
+ throw attributeUnexpected(name, parser.getAttributeName(i));
+ }
+ break;
default:
throw attributeUnexpected(name, parser.getAttributeName(i));
}
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt
index 06c390ebc..107d6e35a 100644
--- a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt
@@ -76,7 +76,12 @@ class ParserConfigInvalidTest {
"ConfigStaticSafetySourceWithNotifications",
R.raw.config_static_safety_source_with_notifications,
"Element static-safety-source invalid",
- "Prohibited attribute notificationsAllowed present"))
+ "Prohibited attribute notificationsAllowed present"),
+ Params(
+ "ConfigStaticSafetySourceWithDeduplicationGroups",
+ R.raw.config_static_safety_source_with_deduplication_groups,
+ "Element static-safety-source invalid",
+ "Prohibited attribute deduplicationGroup present"))
fun parametersTiramisu(): Array<Params> =
arrayOf(
diff --git a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt
index 02fbb5950..34d91e6bf 100644
--- a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt
+++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt
@@ -69,7 +69,12 @@ class ParserConfigValidTest {
.setSearchTermsResId(R.string.reference)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup("group")
+ }
+ }
.build())
.addSafetySource(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -85,6 +90,12 @@ class ParserConfigValidTest {
.setSearchTermsResId(R.string.reference)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup("group")
+ }
+ }
.build())
.addSafetySource(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -154,7 +165,12 @@ class ParserConfigValidTest {
.setMaxSeverityLevel(300)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup("group")
+ }
+ }
.build())
.build())
.addSafetySourcesGroup(
diff --git a/SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_deduplication_groups.xml b/SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_deduplication_groups.xml
new file mode 100644
index 000000000..b75969ae1
--- /dev/null
+++ b/SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_deduplication_groups.xml
@@ -0,0 +1,32 @@
+<!--
+ ~ 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.
+ -->
+
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="id"
+ title="@com.android.safetycenter.config.tests:string/reference"
+ summary="@com.android.safetycenter.config.tests:string/reference">
+ <static-safety-source
+ id="id"
+ title="@com.android.safetycenter.config.tests:string/reference"
+ summary="@com.android.safetycenter.config.tests:string/reference"
+ intentAction="intent"
+ profile="primary_profile_only"
+ deduplicationGroup="group"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config> \ No newline at end of file
diff --git a/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml b/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml
index 8d9e3aa24..eec65ec7e 100644
--- a/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml
+++ b/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml
@@ -25,7 +25,8 @@
searchTerms="@com.android.safetycenter.config.tests:string/reference"
loggingAllowed="false"
refreshOnPageOpenAllowed="true"
- notificationsAllowed="true"/>
+ notificationsAllowed="true"
+ deduplicationGroup="group"/>
<dynamic-safety-source
id="@com.android.safetycenter.config.tests:string/dynamic_all_references_id"
packageName="@com.android.safetycenter.config.tests:string/dynamic_all_references_package_name"
@@ -38,7 +39,9 @@
maxSeverityLevel="@com.android.safetycenter.config.tests:string/dynamic_all_references_max_severity_level"
searchTerms="@com.android.safetycenter.config.tests:string/reference"
loggingAllowed="@com.android.safetycenter.config.tests:string/dynamic_all_references_logging_allowed"
- refreshOnPageOpenAllowed="@com.android.safetycenter.config.tests:string/dynamic_all_references_refresh_on_page_open_allowed"/>
+ refreshOnPageOpenAllowed="@com.android.safetycenter.config.tests:string/dynamic_all_references_refresh_on_page_open_allowed"
+ notificationsAllowed="@com.android.safetycenter.config.tests:string/dynamic_all_references_notifications_allowed"
+ deduplicationGroup="@com.android.safetycenter.config.tests:string/dynamic_all_references_deduplication_group"/>
<dynamic-safety-source
id="dynamic_disabled"
packageName="package"
@@ -92,7 +95,8 @@
maxSeverityLevel="300"
loggingAllowed="false"
refreshOnPageOpenAllowed="true"
- notificationsAllowed="true"/>
+ notificationsAllowed="true"
+ deduplicationGroup="group"/>
</safety-sources-group>
<safety-sources-group
id="mixed"
diff --git a/SafetyCenter/Config/tests/res/values/strings.xml b/SafetyCenter/Config/tests/res/values/strings.xml
index 195f56c2a..d7b8b13c5 100644
--- a/SafetyCenter/Config/tests/res/values/strings.xml
+++ b/SafetyCenter/Config/tests/res/values/strings.xml
@@ -26,4 +26,6 @@
<string name="dynamic_all_references_max_severity_level" translatable="false">300</string>
<string name="dynamic_all_references_logging_allowed" translatable="false">false</string>
<string name="dynamic_all_references_refresh_on_page_open_allowed" translatable="false">true</string>
+ <string name="dynamic_all_references_notifications_allowed" translatable="false">true</string>
+ <string name="dynamic_all_references_deduplication_group" translatable="false">group</string>
</resources>
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index 8529f0eee..887d3fec7 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -479,6 +479,7 @@ package android.safetycenter.config {
public final class SafetySource implements android.os.Parcelable {
method public boolean areNotificationsAllowed();
method public int describeContents();
+ method @Nullable public String getDeduplicationGroup();
method @NonNull public String getId();
method public int getInitialDisplayState();
method @Nullable public String getIntentAction();
@@ -508,6 +509,7 @@ package android.safetycenter.config {
public static final class SafetySource.Builder {
ctor public SafetySource.Builder(int);
method @NonNull public android.safetycenter.config.SafetySource build();
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setDeduplicationGroup(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setId(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setInitialDisplayState(int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setIntentAction(@Nullable String);
diff --git a/framework-s/java/android/safetycenter/SafetySourceIssue.java b/framework-s/java/android/safetycenter/SafetySourceIssue.java
index afc4f071f..f4a369a4b 100644
--- a/framework-s/java/android/safetycenter/SafetySourceIssue.java
+++ b/framework-s/java/android/safetycenter/SafetySourceIssue.java
@@ -380,7 +380,10 @@ public final class SafetySourceIssue implements Parcelable {
* deduplication identifiers.
*
* <p>Deduplication identifier will be used to identify duplicate issues. This identifier
- * applies globally across all safety sources sending data to SafetyCenter.
+ * applies across all safety sources which are part of the same deduplication group.
+ * Deduplication groups can be set, for each source, in the SafetyCenter config. Therefore, two
+ * issues are considered duplicate if their sources are part of the same deduplication group and
+ * they have the same deduplication identifier.
*
* <p>Out of all issues that are found to be duplicates, only one will be shown in the UI (the
* one with the highest severity, or in case of same severities, the one placed highest in the
diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java
index 9c8c279c3..d3d9cb9f7 100644
--- a/framework-s/java/android/safetycenter/config/SafetySource.java
+++ b/framework-s/java/android/safetycenter/config/SafetySource.java
@@ -171,6 +171,7 @@ public final class SafetySource implements Parcelable {
.setRefreshOnPageOpenAllowed(in.readBoolean());
if (SdkLevel.isAtLeastU()) {
builder.setNotificationsAllowed(in.readBoolean());
+ builder.setDeduplicationGroup(in.readString());
}
return builder.build();
}
@@ -195,6 +196,7 @@ public final class SafetySource implements Parcelable {
private final boolean mLoggingAllowed;
private final boolean mRefreshOnPageOpenAllowed;
private final boolean mNotificationsAllowed;
+ @Nullable final String mDeduplicationGroup;
private SafetySource(
@SafetySourceType int type,
@@ -210,7 +212,8 @@ public final class SafetySource implements Parcelable {
@StringRes int searchTermsResId,
boolean loggingAllowed,
boolean refreshOnPageOpenAllowed,
- boolean notificationsAllowed) {
+ boolean notificationsAllowed,
+ @Nullable String deduplicationGroup) {
mType = type;
mId = id;
mPackageName = packageName;
@@ -225,6 +228,7 @@ public final class SafetySource implements Parcelable {
mLoggingAllowed = loggingAllowed;
mRefreshOnPageOpenAllowed = refreshOnPageOpenAllowed;
mNotificationsAllowed = notificationsAllowed;
+ mDeduplicationGroup = deduplicationGroup;
}
/** Returns the type of this safety source. */
@@ -442,6 +446,21 @@ public final class SafetySource implements Parcelable {
return mNotificationsAllowed;
}
+ /**
+ * Returns the deduplication group this source belongs to.
+ *
+ * <p>Sources which are part of the same deduplication group can coordinate to deduplicate their
+ * issues.
+ */
+ @Nullable
+ @RequiresApi(UPSIDE_DOWN_CAKE)
+ public String getDeduplicationGroup() {
+ if (!SdkLevel.isAtLeastU()) {
+ throw new UnsupportedOperationException();
+ }
+ return mDeduplicationGroup;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -460,7 +479,8 @@ public final class SafetySource implements Parcelable {
&& mSearchTermsResId == that.mSearchTermsResId
&& mLoggingAllowed == that.mLoggingAllowed
&& mRefreshOnPageOpenAllowed == that.mRefreshOnPageOpenAllowed
- && mNotificationsAllowed == that.mNotificationsAllowed;
+ && mNotificationsAllowed == that.mNotificationsAllowed
+ && Objects.equals(mDeduplicationGroup, that.mDeduplicationGroup);
}
@Override
@@ -479,7 +499,8 @@ public final class SafetySource implements Parcelable {
mSearchTermsResId,
mLoggingAllowed,
mRefreshOnPageOpenAllowed,
- mNotificationsAllowed);
+ mNotificationsAllowed,
+ mDeduplicationGroup);
}
@Override
@@ -513,6 +534,8 @@ public final class SafetySource implements Parcelable {
+ mRefreshOnPageOpenAllowed
+ ", mNotificationsAllowed="
+ mNotificationsAllowed
+ + ", mDeduplicationGroup="
+ + mDeduplicationGroup
+ '}';
}
@@ -538,6 +561,7 @@ public final class SafetySource implements Parcelable {
dest.writeBoolean(mRefreshOnPageOpenAllowed);
if (SdkLevel.isAtLeastU()) {
dest.writeBoolean(mNotificationsAllowed);
+ dest.writeString(mDeduplicationGroup);
}
}
@@ -558,6 +582,7 @@ public final class SafetySource implements Parcelable {
@Nullable private Boolean mLoggingAllowed;
@Nullable private Boolean mRefreshOnPageOpenAllowed;
@Nullable private Boolean mNotificationsAllowed;
+ @Nullable private String mDeduplicationGroup;
/** Creates a {@link Builder} for a {@link SafetySource}. */
public Builder(@SafetySourceType int type) {
@@ -766,6 +791,25 @@ public final class SafetySource implements Parcelable {
}
/**
+ * Sets the deduplication group for this source.
+ *
+ * <p>Sources which are part of the same deduplication group can coordinate to deduplicate
+ * issues that they're sending to SafetyCenter by providing the same deduplication
+ * identifier with those issues.
+ *
+ * <p>The deduplication group property is prohibited for sources of type static.
+ */
+ @NonNull
+ @RequiresApi(UPSIDE_DOWN_CAKE)
+ public Builder setDeduplicationGroup(@Nullable String deduplicationGroup) {
+ if (!SdkLevel.isAtLeastU()) {
+ throw new UnsupportedOperationException();
+ }
+ mDeduplicationGroup = deduplicationGroup;
+ return this;
+ }
+
+ /**
* Creates the {@link SafetySource} defined by this {@link Builder}.
*
* <p>Throws an {@link IllegalStateException} if any constraint on the safety source is
@@ -868,6 +912,9 @@ public final class SafetySource implements Parcelable {
false,
isStatic,
false);
+
+ BuilderUtils.validateAttribute(
+ mDeduplicationGroup, "deduplicationGroup", false, isStatic);
}
return new SafetySource(
@@ -884,7 +931,8 @@ public final class SafetySource implements Parcelable {
searchTermsResId,
loggingAllowed,
refreshOnPageOpenAllowed,
- notificationsAllowed);
+ notificationsAllowed,
+ mDeduplicationGroup);
}
}
}
diff --git a/framework-s/java/android/safetycenter/config/safety_center_config.xsd b/framework-s/java/android/safetycenter/config/safety_center_config.xsd
index 8d9903e16..75b31c166 100644
--- a/framework-s/java/android/safetycenter/config/safety_center_config.xsd
+++ b/framework-s/java/android/safetycenter/config/safety_center_config.xsd
@@ -72,6 +72,7 @@
default="false"/>
<xsd:attribute name="notificationsAllowed" type="booleanOrStringResourceName"
default="false"/>
+ <xsd:attribute name="deduplicationGroup" type="stringOrStringResourceName"/>
</xsd:complexType>
<xsd:complexType name="issue-only-safety-source">
@@ -85,6 +86,7 @@
default="false"/>
<xsd:attribute name="notificationsAllowed" type="booleanOrStringResourceName"
default="false"/>
+ <xsd:attribute name="deduplicationGroup" type="stringOrStringResourceName"/>
</xsd:complexType>
<xsd:complexType name="static-safety-source">
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
index 60a14794b..393ae38c1 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
@@ -259,6 +259,20 @@ class SafetySourceTest {
assertThat(issueOnlyAllOptional().areNotificationsAllowed()).isTrue()
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ fun getDeduplicationGroupsList_returnsDeduplicationGroups() {
+ assertThat(DYNAMIC_BAREBONE.deduplicationGroup).isNull()
+ assertThat(dynamicAllOptional().deduplicationGroup).isEqualTo(DEDUPLICATION_GROUP)
+ assertThat(DYNAMIC_DISABLED.deduplicationGroup).isNull()
+ assertThat(DYNAMIC_HIDDEN.deduplicationGroup).isNull()
+ assertThat(DYNAMIC_HIDDEN_WITH_SEARCH.deduplicationGroup).isNull()
+ assertThat(STATIC_BAREBONE.deduplicationGroup).isNull()
+ assertThat(STATIC_ALL_OPTIONAL.deduplicationGroup).isNull()
+ assertThat(ISSUE_ONLY_BAREBONE.deduplicationGroup).isNull()
+ assertThat(issueOnlyAllOptional().deduplicationGroup).isEqualTo(DEDUPLICATION_GROUP)
+ }
+
@Test
fun describeContents_returns0() {
assertThat(DYNAMIC_BAREBONE.describeContents()).isEqualTo(0)
@@ -304,7 +318,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(DYNAMIC_HIDDEN)
.addEqualityGroup(DYNAMIC_HIDDEN_WITH_SEARCH)
@@ -327,7 +346,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -343,6 +367,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -358,6 +388,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -373,6 +409,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -388,6 +430,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -403,6 +451,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -410,7 +464,6 @@ class SafetySourceTest {
.setPackageName(PACKAGE_NAME)
.setProfile(SafetySource.PROFILE_PRIMARY)
.setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -426,6 +479,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -441,6 +500,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -456,6 +521,12 @@ class SafetySourceTest {
.setSearchTermsResId(-1)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -471,6 +542,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(true)
.setRefreshOnPageOpenAllowed(true)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
.addEqualityGroup(
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -486,7 +563,51 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(false)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build())
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .setNotificationsAllowed(false)
+ .setDeduplicationGroup(DEDUPLICATION_GROUP)
+ .build())
+ addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .setNotificationsAllowed(true)
+ .setDeduplicationGroup("other_deduplication_group")
+ .build())
+ }
+ }
.test()
}
@@ -505,6 +626,7 @@ class SafetySourceTest {
private const val STATIC_ALL_OPTIONAL_ID = "static_all_optional"
private const val ISSUE_ONLY_BAREBONE_ID = "issue_only_barebone"
private const val ISSUE_ONLY_ALL_OPTIONAL_ID = "issue_only_all_optional"
+ private const val DEDUPLICATION_GROUP = "deduplication_group"
internal val DYNAMIC_BAREBONE =
SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
@@ -530,7 +652,12 @@ class SafetySourceTest {
.setSearchTermsResId(REFERENCE_RES_ID)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build()
private val DYNAMIC_DISABLED =
@@ -598,7 +725,12 @@ class SafetySourceTest {
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setLoggingAllowed(false)
.setRefreshOnPageOpenAllowed(true)
- .apply { if (SdkLevel.isAtLeastU()) setNotificationsAllowed(true) }
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup(DEDUPLICATION_GROUP)
+ }
+ }
.build()
}
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt
index ab5db20e2..359420f5b 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt
@@ -26,6 +26,7 @@ import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY
import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_STATIC
import android.safetycenter.config.SafetySourcesGroup
import android.safetycenter.cts.testing.SettingsPackage.getSettingsPackageName
+import com.android.modules.utils.build.SdkLevel
/**
* A class that provides [SafetyCenterConfig] objects and associated constants to facilitate setting
@@ -508,6 +509,12 @@ object SafetyCenterCtsConfigs {
.setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
.setSearchTermsResId(android.R.string.ok)
.setLoggingAllowed(false)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup("group")
+ }
+ }
.build())
.addSafetySource(
dynamicSafetySourceBuilder(DYNAMIC_DISABLED_ID)
@@ -553,6 +560,12 @@ object SafetyCenterCtsConfigs {
issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID)
.setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
.setLoggingAllowed(false)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup("group")
+ }
+ }
.build())
.build())
.addSafetySourcesGroup(
@@ -618,6 +631,12 @@ object SafetyCenterCtsConfigs {
issueOnlyAllProfileSafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID)
.setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
.setLoggingAllowed(false)
+ .apply {
+ if (SdkLevel.isAtLeastU()) {
+ setNotificationsAllowed(true)
+ setDeduplicationGroup("group")
+ }
+ }
.build())
.build())
.addSafetySourcesGroup(