diff options
author | 2022-11-14 16:04:02 +0000 | |
---|---|---|
committer | 2022-11-30 08:06:53 +0000 | |
commit | 46aa98e75473df7c2c4212b2ab85a8cdc5125224 (patch) | |
tree | aad7f3de041af39c490e7b072f98348ddb41ba3b | |
parent | a84dc9c4d38cc0bb0a8e10722c00f3a372dacc58 (diff) |
Add SafetySource.getPackageCertificateHashes
Cert hashes will be used in a signature check on other APIs where
currently a package name only check is used.
Test: atest SafetySourceTest SafetyCenterConfigTests
Bug: 252726218
Change-Id: Iac01b010e8ef39e9217738642d90bc5cf1d141ed
14 files changed, 307 insertions, 10 deletions
diff --git a/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java b/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java index e71bf9e74..f7faf9e27 100644 --- a/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java +++ b/SafetyCenter/Config/java/com/android/safetycenter/config/SafetyCenterConfigParser.java @@ -76,6 +76,7 @@ public final class SafetyCenterConfigParser { "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 ATTR_SAFETY_SOURCE_PACKAGE_CERT_HASHES = "packageCertificateHashes"; 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_GROUP_TYPE_STATEFUL = "stateful"; @@ -365,6 +366,22 @@ public final class SafetyCenterConfigParser { throw attributeUnexpected(name, parser.getAttributeName(i)); } break; + case ATTR_SAFETY_SOURCE_PACKAGE_CERT_HASHES: + if (SdkLevel.isAtLeastU()) { + String commaSeparatedHashes = + parseStringResourceValue( + parser.getAttributeValue(i), + name, + parser.getAttributeName(i), + resources); + String[] splits = commaSeparatedHashes.split(","); + for (int j = 0; j < splits.length; j++) { + builder.addPackageCertificateHash(splits[j]); + } + } 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 c919f20f0..fc169fd5e 100644 --- a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt +++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigInvalidTest.kt @@ -340,6 +340,12 @@ class ParserConfigInvalidTest { "Prohibited attribute packageName present", !SdkLevel.isAtLeastU()), Params( + "ConfigStaticSafetySourceWithPackageCertficates", + R.raw.config_static_safety_source_with_package_certs, + "Element static-safety-source invalid", + "Prohibited attribute packageCertificateHashes present", + SdkLevel.isAtLeastU()), + Params( "ConfigStaticSafetySourceWithPrimaryAndWork", R.raw.config_static_safety_source_with_primary_and_work, "Element static-safety-source invalid", 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 28a8bd20a..573725582 100644 --- a/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt +++ b/SafetyCenter/Config/tests/java/com/android/safetycenter/config/ParserConfigValidTest.kt @@ -73,6 +73,8 @@ class ParserConfigValidTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup("group") + addPackageCertificateHash("feed1") + addPackageCertificateHash("feed2") } } .build()) @@ -94,6 +96,8 @@ class ParserConfigValidTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup("group") + addPackageCertificateHash("feed1") + addPackageCertificateHash("feed2") } } .build()) @@ -170,6 +174,8 @@ class ParserConfigValidTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup("group") + addPackageCertificateHash("feed1") + addPackageCertificateHash("feed2") } } .build()) diff --git a/SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_package_certs.xml b/SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_package_certs.xml new file mode 100644 index 000000000..2a99d5617 --- /dev/null +++ b/SafetyCenter/Config/tests/res/raw-v34/config_static_safety_source_with_package_certs.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" + packageCertificateHashes="feed1,feed2"/> + </safety-sources-group> + </safety-sources-config> +</safety-center-config> diff --git a/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml b/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml index 3b5813bca..f9e7fbf27 100644 --- a/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml +++ b/SafetyCenter/Config/tests/res/raw-v34/config_valid.xml @@ -26,7 +26,8 @@ loggingAllowed="false" refreshOnPageOpenAllowed="true" notificationsAllowed="true" - deduplicationGroup="group"/> + deduplicationGroup="group" + packageCertificateHashes="feed1,feed2"/> <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" @@ -41,7 +42,8 @@ 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" notificationsAllowed="@com.android.safetycenter.config.tests:string/dynamic_all_references_notifications_allowed" - deduplicationGroup="@com.android.safetycenter.config.tests:string/dynamic_all_references_deduplication_group"/> + deduplicationGroup="@com.android.safetycenter.config.tests:string/dynamic_all_references_deduplication_group" + packageCertificateHashes="@com.android.safetycenter.config.tests:string/dynamic_all_references_package_cert_hashes"/> <dynamic-safety-source id="dynamic_disabled" packageName="package" @@ -97,7 +99,8 @@ loggingAllowed="false" refreshOnPageOpenAllowed="true" notificationsAllowed="true" - deduplicationGroup="group"/> + deduplicationGroup="group" + packageCertificateHashes="feed1,feed2"/> </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 d7b8b13c5..a625c5225 100644 --- a/SafetyCenter/Config/tests/res/values/strings.xml +++ b/SafetyCenter/Config/tests/res/values/strings.xml @@ -28,4 +28,5 @@ <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> + <string name="dynamic_all_references_package_cert_hashes" translatable="false">feed1,feed2</string> </resources> diff --git a/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java b/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java index e1300de32..81bedc860 100644 --- a/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java +++ b/SafetyCenter/ConfigLintChecker/java/android/os/Parcel.java @@ -29,6 +29,8 @@ public interface Parcel { int readInt(); /** Method used in the Safety Center config data structures. */ String readString(); + /** Method used in the Safety Center config data structures. */ + ArrayList<String> createStringArrayList(); /** Method used in the Safety Center config data structures. */ void writeBoolean(boolean value); @@ -37,5 +39,7 @@ public interface Parcel { /** Method used in the Safety Center config data structures. */ void writeString(String value); /** Method used in the Safety Center config data structures. */ + void writeStringList(List<String> value); + /** Method used in the Safety Center config data structures. */ <T extends Parcelable> void writeTypedList(List<T> value); } diff --git a/SafetyCenter/ConfigLintChecker/java/android/util/ArraySet.java b/SafetyCenter/ConfigLintChecker/java/android/util/ArraySet.java new file mode 100644 index 000000000..cfc864c65 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/util/ArraySet.java @@ -0,0 +1,28 @@ +/* + * 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 android.util; + +import java.util.HashSet; + +/** + * A simple ArraySet implementation for the lint checker. + * + * <p>It's not array based, but for this simple purpose that doesn't matter. + * + * @param <E> the type of elements maintained by this set + */ +public final class ArraySet<E> extends HashSet<E> {} diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt index ae7008e64..8aca658d3 100644 --- a/framework-s/api/system-current.txt +++ b/framework-s/api/system-current.txt @@ -494,6 +494,7 @@ package android.safetycenter.config { method @Nullable public String getIntentAction(); method public int getMaxSeverityLevel(); method @Nullable public String getOptionalPackageName(); + method @NonNull public java.util.Set<java.lang.String> getPackageCertificateHashes(); method @NonNull public String getPackageName(); method public int getProfile(); method @StringRes public int getSearchTermsResId(); @@ -518,6 +519,7 @@ package android.safetycenter.config { public static final class SafetySource.Builder { ctor public SafetySource.Builder(int); + method @NonNull public android.safetycenter.config.SafetySource.Builder addPackageCertificateHash(@NonNull String); 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); diff --git a/framework-s/java/android/safetycenter/config/BuilderUtils.java b/framework-s/java/android/safetycenter/config/BuilderUtils.java index e0e08183d..35ec39cc5 100644 --- a/framework-s/java/android/safetycenter/config/BuilderUtils.java +++ b/framework-s/java/android/safetycenter/config/BuilderUtils.java @@ -25,6 +25,7 @@ import android.content.res.Resources; import androidx.annotation.RequiresApi; +import java.util.Collection; import java.util.Objects; @RequiresApi(TIRAMISU) @@ -39,12 +40,12 @@ final class BuilderUtils { boolean prohibited, @Nullable Object defaultValue) { if (attribute == null && required) { - throw new IllegalStateException("Required attribute " + name + " missing"); + throwRequiredAttributeMissing(name); } boolean nonDefaultValueProvided = !Objects.equals(attribute, defaultValue); boolean checkProhibited = prohibited && nonDefaultValueProvided; if (attribute != null && checkProhibited) { - throw new IllegalStateException("Prohibited attribute " + name + " present"); + throwProhibitedAttributePresent(name); } } @@ -67,7 +68,7 @@ final class BuilderUtils { return Resources.ID_NULL; } if (required && value == Resources.ID_NULL) { - throw new IllegalStateException("Required attribute " + name + " invalid"); + throwRequiredAttributeInvalid(name); } return value; } @@ -119,4 +120,37 @@ final class BuilderUtils { } return value; } + + /** + * Validates a collection argument from a builder. + * + * <ul> + * <li>If {@code required}, a non-empty collection must be supplied. + * <li>If {@code prohibited}, an empty collection must be supplied. + * </ul> + */ + static <T> void validateCollection( + @NonNull Collection<T> value, + @NonNull String name, + boolean required, + boolean prohibited) { + if (value.isEmpty() && required) { + throwRequiredAttributeMissing(name); + } + if (!value.isEmpty() && prohibited) { + throwProhibitedAttributePresent(name); + } + } + + static void throwRequiredAttributeMissing(@NonNull String attribute) { + throw new IllegalStateException("Required attribute " + attribute + " missing"); + } + + static void throwProhibitedAttributePresent(@NonNull String attribute) { + throw new IllegalStateException("Prohibited attribute " + attribute + " present"); + } + + static void throwRequiredAttributeInvalid(@NonNull String attribute) { + throw new IllegalStateException("Required attribute " + attribute + " invalid"); + } } diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java index e3db49300..6c4c5b766 100644 --- a/framework-s/java/android/safetycenter/config/SafetySource.java +++ b/framework-s/java/android/safetycenter/config/SafetySource.java @@ -27,6 +27,7 @@ import android.annotation.SystemApi; import android.content.res.Resources; import android.os.Parcel; import android.os.Parcelable; +import android.util.ArraySet; import androidx.annotation.RequiresApi; @@ -34,7 +35,9 @@ import com.android.modules.utils.build.SdkLevel; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.List; import java.util.Objects; +import java.util.Set; /** * Data class used to represent the initial configuration of a safety source. @@ -172,6 +175,10 @@ public final class SafetySource implements Parcelable { if (SdkLevel.isAtLeastU()) { builder.setNotificationsAllowed(in.readBoolean()); builder.setDeduplicationGroup(in.readString()); + List<String> certs = in.createStringArrayList(); + for (int i = 0; i < certs.size(); i++) { + builder.addPackageCertificateHash(certs.get(i)); + } } return builder.build(); } @@ -197,6 +204,7 @@ public final class SafetySource implements Parcelable { private final boolean mRefreshOnPageOpenAllowed; private final boolean mNotificationsAllowed; @Nullable final String mDeduplicationGroup; + @NonNull private final Set<String> mPackageCertificateHashes; private SafetySource( @SafetySourceType int type, @@ -213,7 +221,8 @@ public final class SafetySource implements Parcelable { boolean loggingAllowed, boolean refreshOnPageOpenAllowed, boolean notificationsAllowed, - @Nullable String deduplicationGroup) { + @Nullable String deduplicationGroup, + @NonNull Set<String> packageCertificateHashes) { mType = type; mId = id; mPackageName = packageName; @@ -229,6 +238,7 @@ public final class SafetySource implements Parcelable { mRefreshOnPageOpenAllowed = refreshOnPageOpenAllowed; mNotificationsAllowed = notificationsAllowed; mDeduplicationGroup = deduplicationGroup; + mPackageCertificateHashes = Set.copyOf(packageCertificateHashes); } /** Returns the type of this safety source. */ @@ -496,6 +506,28 @@ public final class SafetySource implements Parcelable { return mDeduplicationGroup; } + /** + * Returns a set of package certificate hashes representing valid signed packages that represent + * this {@link SafetySource}. + * + * <p>If one or more certificate hashes are set, Safety Center will validate that a package + * calling {@link android.safetycenter.SafetyCenterManager#setSafetySourceData} is signed with + * one of the certificates provided. + * + * <p>The default value is an empty {@code Set}, in which case only the package name is + * validated. + * + * @see Builder#addPackageCertificateHash(String) + */ + @NonNull + @RequiresApi(UPSIDE_DOWN_CAKE) + public Set<String> getPackageCertificateHashes() { + if (!SdkLevel.isAtLeastU()) { + throw new UnsupportedOperationException(); + } + return mPackageCertificateHashes; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -515,7 +547,8 @@ public final class SafetySource implements Parcelable { && mLoggingAllowed == that.mLoggingAllowed && mRefreshOnPageOpenAllowed == that.mRefreshOnPageOpenAllowed && mNotificationsAllowed == that.mNotificationsAllowed - && Objects.equals(mDeduplicationGroup, that.mDeduplicationGroup); + && Objects.equals(mDeduplicationGroup, that.mDeduplicationGroup) + && Objects.equals(mPackageCertificateHashes, that.mPackageCertificateHashes); } @Override @@ -535,7 +568,8 @@ public final class SafetySource implements Parcelable { mLoggingAllowed, mRefreshOnPageOpenAllowed, mNotificationsAllowed, - mDeduplicationGroup); + mDeduplicationGroup, + mPackageCertificateHashes); } @Override @@ -571,6 +605,8 @@ public final class SafetySource implements Parcelable { + mNotificationsAllowed + ", mDeduplicationGroup=" + mDeduplicationGroup + + ", mPackageCertificateHashes=" + + mPackageCertificateHashes + '}'; } @@ -597,6 +633,7 @@ public final class SafetySource implements Parcelable { if (SdkLevel.isAtLeastU()) { dest.writeBoolean(mNotificationsAllowed); dest.writeString(mDeduplicationGroup); + dest.writeStringList(List.copyOf(mPackageCertificateHashes)); } } @@ -618,6 +655,7 @@ public final class SafetySource implements Parcelable { @Nullable private Boolean mRefreshOnPageOpenAllowed; @Nullable private Boolean mNotificationsAllowed; @Nullable private String mDeduplicationGroup; + @NonNull private final ArraySet<String> mPackageCertificateHashes = new ArraySet<>(); /** Creates a {@link Builder} for a {@link SafetySource}. */ public Builder(@SafetySourceType int type) { @@ -845,6 +883,22 @@ public final class SafetySource implements Parcelable { } /** + * Adds a package certificate hash to the {@link #getPackageCertificateHashes()} property of + * this {@link SafetySource}. + * + * @see #getPackageCertificateHashes() + */ + @NonNull + @RequiresApi(UPSIDE_DOWN_CAKE) + public Builder addPackageCertificateHash(@NonNull String packageCertificateHash) { + if (!SdkLevel.isAtLeastU()) { + throw new UnsupportedOperationException(); + } + mPackageCertificateHashes.add(packageCertificateHash); + return this; + } + + /** * Creates the {@link SafetySource} defined by this {@link Builder}. * * <p>Throws an {@link IllegalStateException} if any constraint on the safety source is @@ -947,6 +1001,7 @@ public final class SafetySource implements Parcelable { String deduplicationGroup = mDeduplicationGroup; boolean notificationsAllowed = false; + Set<String> packageCertificateHashes = Set.copyOf(mPackageCertificateHashes); if (SdkLevel.isAtLeastU()) { notificationsAllowed = BuilderUtils.validateBoolean( @@ -958,6 +1013,8 @@ public final class SafetySource implements Parcelable { BuilderUtils.validateAttribute( deduplicationGroup, "deduplicationGroup", false, isStatic); + BuilderUtils.validateCollection( + packageCertificateHashes, "packageCertificateHashes", false, isStatic); } return new SafetySource( @@ -975,7 +1032,8 @@ public final class SafetySource implements Parcelable { loggingAllowed, refreshOnPageOpenAllowed, notificationsAllowed, - deduplicationGroup); + deduplicationGroup, + packageCertificateHashes); } } } diff --git a/framework-s/java/android/safetycenter/config/safety_center_config-v34.xsd b/framework-s/java/android/safetycenter/config/safety_center_config-v34.xsd index fbf62393b..3a70fa065 100644 --- a/framework-s/java/android/safetycenter/config/safety_center_config-v34.xsd +++ b/framework-s/java/android/safetycenter/config/safety_center_config-v34.xsd @@ -55,6 +55,8 @@ <!-- id must be unique among safety sources --> <xsd:attribute name="id" type="stringOrStringResourceName" use="required"/> <xsd:attribute name="packageName" type="stringOrStringResourceName" use="required"/> + <!-- optional comma-separated set of certficate hashes, if provided will be used for validation. --> + <xsd:attribute name="packageCertificateHashes" type="stringOrStringResourceName"/> <!-- title is required if initialDisplayState is not set to hidden or if searchTerms are provided --> <xsd:attribute name="title" type="runtimeStringResourceName"/> <!-- titleForWork is required if profile is set to all_profiles, and initialDisplayState is not set to hidden or if searchTerms are provided --> @@ -81,6 +83,8 @@ <!-- id must be unique among safety sources --> <xsd:attribute name="id" type="stringOrStringResourceName" use="required"/> <xsd:attribute name="packageName" type="stringOrStringResourceName" use="required"/> + <!-- optional comma-separated set of certficate hashes, if provided will be used for validation. --> + <xsd:attribute name="packageCertificateHashes" type="stringOrStringResourceName"/> <xsd:attribute name="profile" type="profileOrStringResourceName" use="required"/> <xsd:attribute name="maxSeverityLevel" type="intOrStringResourceName" default="2147483647"/> <xsd:attribute name="loggingAllowed" type="booleanOrStringResourceName" default="true"/> 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 d116a8468..66b976b31 100644 --- a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt +++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt @@ -287,6 +287,20 @@ class SafetySourceTest { assertThat(issueOnlyAllOptional().deduplicationGroup).isEqualTo(DEDUPLICATION_GROUP) } + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake") + @Test + fun getPackageCertificateHashes_returnsPackageCerts() { + assertThat(DYNAMIC_BAREBONE.packageCertificateHashes).isEmpty() + assertThat(dynamicAllOptional().packageCertificateHashes).containsExactly(HASH1) + assertThat(DYNAMIC_DISABLED.packageCertificateHashes).isEmpty() + assertThat(DYNAMIC_HIDDEN.packageCertificateHashes).isEmpty() + assertThat(DYNAMIC_HIDDEN_WITH_SEARCH.packageCertificateHashes).isEmpty() + assertThat(STATIC_BAREBONE.packageCertificateHashes).isEmpty() + assertThat(STATIC_ALL_OPTIONAL.packageCertificateHashes).isEmpty() + assertThat(ISSUE_ONLY_BAREBONE.packageCertificateHashes).isEmpty() + assertThat(issueOnlyAllOptional().packageCertificateHashes).containsExactly(HASH1, HASH2) + } + @Test fun describeContents_returns0() { assertThat(DYNAMIC_BAREBONE.describeContents()).isEqualTo(0) @@ -336,6 +350,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -364,6 +379,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -385,6 +401,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -406,6 +423,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -427,6 +445,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -448,6 +467,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -469,6 +489,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -497,6 +518,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -518,6 +540,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -539,6 +562,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -560,6 +584,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -581,6 +606,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build()) @@ -602,6 +628,7 @@ class SafetySourceTest { .setRefreshOnPageOpenAllowed(true) .setNotificationsAllowed(false) .setDeduplicationGroup(DEDUPLICATION_GROUP) + .addPackageCertificateHash(HASH1) .build()) addEqualityGroup( SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC) @@ -619,6 +646,64 @@ class SafetySourceTest { .setRefreshOnPageOpenAllowed(true) .setNotificationsAllowed(true) .setDeduplicationGroup("other_deduplication_group") + .addPackageCertificateHash(HASH1) + .build()) + // With no package cert hashes provided + 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(DEDUPLICATION_GROUP) + .build()) + // With longer package cert hash list + 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(DEDUPLICATION_GROUP) + .addPackageCertificateHash(HASH1) + .addPackageCertificateHash(HASH2) + .build()) + // With package cert hash list with different value + 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(DEDUPLICATION_GROUP) + .addPackageCertificateHash(HASH2) .build()) } } @@ -641,6 +726,8 @@ class SafetySourceTest { 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" + private const val HASH1 = "feed1" + private const val HASH2 = "feed2" internal val DYNAMIC_BAREBONE = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC) @@ -670,6 +757,7 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) } } .build() @@ -744,6 +832,8 @@ class SafetySourceTest { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup(DEDUPLICATION_GROUP) + addPackageCertificateHash(HASH1) + addPackageCertificateHash(HASH2) } } .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 ea6b07851..7f02a3717 100644 --- a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt +++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterCtsConfigs.kt @@ -264,6 +264,12 @@ object SafetyCenterCtsConfigs { /** Package name for the [DYNAMIC_OTHER_PACKAGE_ID] source. */ const val OTHER_PACKAGE_NAME = "other_package_name" + /** Hash of a package certificate for all "ALL_OPTIONAL" sources. */ + private const val PACKAGE_CERT_HASH_1 = "feed1" + + /** Second hash of a package certificate for all "ALL_OPTIONAL" sources. */ + private const val PACKAGE_CERT_HASH_2 = "feed2" + /** A Simple [SafetyCenterConfig] with an issue only source. */ val ISSUE_ONLY_SOURCE_CONFIG = singleSourceConfig(issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID).build()) @@ -528,6 +534,8 @@ object SafetyCenterCtsConfigs { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup("group") + addPackageCertificateHash(PACKAGE_CERT_HASH_1) + addPackageCertificateHash(PACKAGE_CERT_HASH_2) } } .build()) @@ -595,6 +603,8 @@ object SafetyCenterCtsConfigs { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup("group") + addPackageCertificateHash(PACKAGE_CERT_HASH_1) + addPackageCertificateHash(PACKAGE_CERT_HASH_2) } } .build()) @@ -667,6 +677,8 @@ object SafetyCenterCtsConfigs { if (SdkLevel.isAtLeastU()) { setNotificationsAllowed(true) setDeduplicationGroup("group") + addPackageCertificateHash(PACKAGE_CERT_HASH_1) + addPackageCertificateHash(PACKAGE_CERT_HASH_2) } } .build()) |