diff options
author | 2024-01-17 15:42:04 +0000 | |
---|---|---|
committer | 2024-02-08 09:58:40 +0000 | |
commit | 1103d313bf297370cd948cf4a78d4a3f748ba87e (patch) | |
tree | 0567393667ee76bd0b35a324043324bd87f03f9d /framework-s/java | |
parent | 48618644f8e98d2df80ae95ec3e8ebfc00139afb (diff) |
Add the titleForPrivateProfile API
This API lets the safety sources set the title for the private
profile in the safety center config file.
This change also temporarily disables the linter. Safety Center team
will look into enabling it later.
Bug: 286539356
Test: manual
Change-Id: I99ab006240883065d290b2d9976f2a7c9bf7905e
Diffstat (limited to 'framework-s/java')
-rw-r--r-- | framework-s/java/android/safetycenter/config/SafetySource.java | 100 | ||||
-rw-r--r-- | framework-s/java/android/safetycenter/config/safety_center_config-v35.xsd | 223 |
2 files changed, 316 insertions, 7 deletions
diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java index 8aa897850..5502ca950 100644 --- a/framework-s/java/android/safetycenter/config/SafetySource.java +++ b/framework-s/java/android/safetycenter/config/SafetySource.java @@ -18,9 +18,11 @@ package android.safetycenter.config; import static android.os.Build.VERSION_CODES.TIRAMISU; import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; +import static android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM; import static java.util.Objects.requireNonNull; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -34,6 +36,7 @@ import android.util.ArraySet; import androidx.annotation.RequiresApi; import com.android.modules.utils.build.SdkLevel; +import com.android.permission.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -182,6 +185,9 @@ public final class SafetySource implements Parcelable { builder.addPackageCertificateHash(certs.get(i)); } } + if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) { + builder.setTitleForPrivateProfileResId(in.readInt()); + } return builder.build(); } @@ -207,6 +213,7 @@ public final class SafetySource implements Parcelable { private final boolean mNotificationsAllowed; @Nullable final String mDeduplicationGroup; @NonNull private final Set<String> mPackageCertificateHashes; + @StringRes private final int mTitleForPrivateProfileResId; private SafetySource( @SafetySourceType int type, @@ -224,7 +231,8 @@ public final class SafetySource implements Parcelable { boolean refreshOnPageOpenAllowed, boolean notificationsAllowed, @Nullable String deduplicationGroup, - @NonNull Set<String> packageCertificateHashes) { + @NonNull Set<String> packageCertificateHashes, + @StringRes int titleForPrivateProfileResId) { mType = type; mId = id; mPackageName = packageName; @@ -241,6 +249,7 @@ public final class SafetySource implements Parcelable { mNotificationsAllowed = notificationsAllowed; mDeduplicationGroup = deduplicationGroup; mPackageCertificateHashes = Set.copyOf(packageCertificateHashes); + mTitleForPrivateProfileResId = titleForPrivateProfileResId; } /** Returns the type of this safety source. */ @@ -347,6 +356,37 @@ public final class SafetySource implements Parcelable { } /** + * Returns the resource id of the title for private profile of this safety source. + * + * <p>The id refers to a string resource that is either accessible from any resource context or + * that is accessible from the same resource context that was used to load the Safety Center + * configuration. The id is {@link Resources#ID_NULL} when a title for private profile is not + * provided. + * + * @throws UnsupportedOperationException if the source is of type {@link + * SafetySource#SAFETY_SOURCE_TYPE_ISSUE_ONLY} or if the profile property of the source is + * set to {@link SafetySource#PROFILE_PRIMARY} + */ + @FlaggedApi(Flags.FLAG_PRIVATE_PROFILE_TITLE_API) + @RequiresApi(VANILLA_ICE_CREAM) + @StringRes + public int getTitleForPrivateProfileResId() { + if (!SdkLevel.isAtLeastV()) { + throw new UnsupportedOperationException( + "getTitleForPrivateProfileResId unsupported for SDKs lower than V"); + } + if (mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY) { + throw new UnsupportedOperationException( + "getTitleForPrivateProfileResId unsupported for issue-only safety source"); + } + if (mProfile == PROFILE_PRIMARY) { + throw new UnsupportedOperationException( + "getTitleForPrivateProfileResId unsupported for primary profile safety source"); + } + return mTitleForPrivateProfileResId; + } + + /** * Returns the resource id of the summary of this safety source. * * <p>The id refers to a string resource that is either accessible from any resource context or @@ -554,7 +594,8 @@ public final class SafetySource implements Parcelable { && mRefreshOnPageOpenAllowed == that.mRefreshOnPageOpenAllowed && mNotificationsAllowed == that.mNotificationsAllowed && Objects.equals(mDeduplicationGroup, that.mDeduplicationGroup) - && Objects.equals(mPackageCertificateHashes, that.mPackageCertificateHashes); + && Objects.equals(mPackageCertificateHashes, that.mPackageCertificateHashes) + && mTitleForPrivateProfileResId == that.mTitleForPrivateProfileResId; } @Override @@ -575,7 +616,8 @@ public final class SafetySource implements Parcelable { mRefreshOnPageOpenAllowed, mNotificationsAllowed, mDeduplicationGroup, - mPackageCertificateHashes); + mPackageCertificateHashes, + mTitleForPrivateProfileResId); } @Override @@ -613,6 +655,8 @@ public final class SafetySource implements Parcelable { + mDeduplicationGroup + ", mPackageCertificateHashes=" + mPackageCertificateHashes + + ", mTitleForPrivateProfileResId=" + + mTitleForPrivateProfileResId + '}'; } @@ -641,6 +685,9 @@ public final class SafetySource implements Parcelable { dest.writeString(mDeduplicationGroup); dest.writeStringList(List.copyOf(mPackageCertificateHashes)); } + if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) { + dest.writeInt(mTitleForPrivateProfileResId); + } } /** Builder class for {@link SafetySource}. */ @@ -662,6 +709,7 @@ public final class SafetySource implements Parcelable { @Nullable private Boolean mNotificationsAllowed; @Nullable private String mDeduplicationGroup; @NonNull private final ArraySet<String> mPackageCertificateHashes = new ArraySet<>(); + @Nullable @StringRes private Integer mTitleForPrivateProfileResId; /** Creates a {@link Builder} for a {@link SafetySource}. */ public Builder(@SafetySourceType int type) { @@ -692,6 +740,7 @@ public final class SafetySource implements Parcelable { mNotificationsAllowed = safetySource.mNotificationsAllowed; mDeduplicationGroup = safetySource.mDeduplicationGroup; mPackageCertificateHashes.addAll(safetySource.mPackageCertificateHashes); + mTitleForPrivateProfileResId = safetySource.mTitleForPrivateProfileResId; } /** @@ -759,6 +808,32 @@ public final class SafetySource implements Parcelable { } /** + * Sets the resource id of the title for work of this safety source. + * + * <p>The id must refer to a string resource that is either accessible from any resource + * context or that is accessible from the same resource context that was used to load the + * Safety Center configuration. The id defaults to {@link Resources#ID_NULL} when a title + * for work is not provided. + * + * <p>The title for work is required if the profile property of the source is set to {@link + * SafetySource#PROFILE_ALL} and either the source is of type static or the source is a + * source of type dynamic that is not hidden and that does not provide search terms. The + * title for work is prohibited for sources of type issue-only and if the profile property + * of the source is not set to {@link SafetySource#PROFILE_ALL}. + */ + @FlaggedApi(Flags.FLAG_PRIVATE_PROFILE_TITLE_API) + @RequiresApi(VANILLA_ICE_CREAM) + @NonNull + public Builder setTitleForPrivateProfileResId(@StringRes int titleForPrivateProfileResId) { + if (!SdkLevel.isAtLeastV()) { + throw new UnsupportedOperationException( + "setTitleForPrivateProfileResId unsupported for SDKs lower than V"); + } + mTitleForPrivateProfileResId = titleForPrivateProfileResId; + return this; + } + + /** * Sets the resource id of the summary of this safety source. * * <p>The id must refer to a string resource that is either accessible from any resource @@ -984,7 +1059,7 @@ public final class SafetySource implements Parcelable { PROFILE_NONE, PROFILE_PRIMARY, PROFILE_ALL); - boolean hasWork = profile == PROFILE_ALL; + boolean hasAllProfiles = profile == PROFILE_ALL; int searchTermsResId = BuilderUtils.validateResId( @@ -1000,8 +1075,8 @@ public final class SafetySource implements Parcelable { BuilderUtils.validateResId( mTitleForWorkResId, "titleForWork", - hasWork && titleRequired, - !hasWork || isIssueOnly); + hasAllProfiles && titleRequired, + !hasAllProfiles || isIssueOnly); int summaryResId = BuilderUtils.validateResId( @@ -1052,6 +1127,16 @@ public final class SafetySource implements Parcelable { packageCertificateHashes, "packageCertificateHashes", false, isStatic); } + int titleForPrivateProfileResId = Resources.ID_NULL; + if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) { + titleForPrivateProfileResId = + BuilderUtils.validateResId( + mTitleForPrivateProfileResId, + "titleForPrivateProfile", + hasAllProfiles && titleRequired, + !hasAllProfiles || isIssueOnly); + } + return new SafetySource( type, id, @@ -1068,7 +1153,8 @@ public final class SafetySource implements Parcelable { refreshOnPageOpenAllowed, notificationsAllowed, deduplicationGroup, - packageCertificateHashes); + packageCertificateHashes, + titleForPrivateProfileResId); } } } diff --git a/framework-s/java/android/safetycenter/config/safety_center_config-v35.xsd b/framework-s/java/android/safetycenter/config/safety_center_config-v35.xsd new file mode 100644 index 000000000..20b1e7655 --- /dev/null +++ b/framework-s/java/android/safetycenter/config/safety_center_config-v35.xsd @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<!-- This file contains comments that define constraints that cannot be covered by the XSD language --> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + version="1.0"> + + <xsd:element name="safety-center-config" type="safety-center-config"/> + + <xsd:complexType name="safety-center-config"> + <xsd:sequence> + <xsd:element name="safety-sources-config" type="safety-sources-config"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="safety-sources-config"> + <xsd:sequence> + <xsd:element + name="safety-sources-group" type="safety-sources-group" + minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="safety-sources-group"> + <xsd:choice minOccurs="1" maxOccurs="unbounded"> + <xsd:element name="dynamic-safety-source" type="dynamic-safety-source"/> + <xsd:element name="static-safety-source" type="static-safety-source"/> + <xsd:element name="issue-only-safety-source" type="issue-only-safety-source"/> + </xsd:choice> + <!-- id must be unique among safety sources groups --> + <xsd:attribute name="id" type="idOrStringResourceName" use="required"/> + <!-- title is required unless the group contains issue only and/or internal sources --> + <xsd:attribute name="title" type="runtimeStringResourceName"/> + <xsd:attribute name="summary" type="runtimeStringResourceName"/> + <xsd:attribute name="statelessIconType" type="statelessIconTypeOrStringResourceName" + default="none"/> + <!-- type is inferred from other attributes and the group content if omitted --> + <xsd:attribute name="type" type="groupTypeOrStringResourceName"/> + </xsd:complexType> + + <xsd:complexType name="dynamic-safety-source"> + <!-- id must be unique among safety sources --> + <xsd:attribute name="id" type="idOrStringResourceName" use="required"/> + <xsd:attribute name="packageName" type="stringOrStringResourceName" use="required"/> + <!-- optional comma-separated set of certificate 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 --> + <!-- titleForWork is prohibited if profile is set to primary_profile_only --> + <xsd:attribute name="titleForWork" type="runtimeStringResourceName"/> + <!-- titleForPrivateProfile is required if profile is set to all_profiles, and initialDisplayState is not set to hidden or if searchTerms are provided --> + <!-- titleForPrivateProfile is prohibited if profile is set to primary_profile_only --> + <xsd:attribute name="titleForPrivateProfile" type="runtimeStringResourceName"/> + <!-- summary is required if initialDisplayState is not set to hidden --> + <xsd:attribute name="summary" type="runtimeStringResourceName"/> + <!-- intentAction is required if initialDisplayState is set to enabled --> + <xsd:attribute name="intentAction" type="stringOrStringResourceName"/> + <xsd:attribute name="profile" type="profile" use="required"/> + <xsd:attribute name="initialDisplayState" type="initialDisplayStateOrStringResourceName" + default="enabled"/> + <xsd:attribute name="maxSeverityLevel" type="intOrStringResourceName" default="2147483647"/> + <xsd:attribute name="searchTerms" type="runtimeStringResourceName"/> + <xsd:attribute name="loggingAllowed" type="booleanOrStringResourceName" default="true"/> + <xsd:attribute name="refreshOnPageOpenAllowed" type="booleanOrStringResourceName" + 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"> + <!-- id must be unique among safety sources --> + <xsd:attribute name="id" type="idOrStringResourceName" use="required"/> + <xsd:attribute name="packageName" type="stringOrStringResourceName" use="required"/> + <!-- optional comma-separated set of certificate 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"/> + <xsd:attribute name="refreshOnPageOpenAllowed" type="booleanOrStringResourceName" + default="false"/> + <xsd:attribute name="notificationsAllowed" type="booleanOrStringResourceName" + default="false"/> + <xsd:attribute name="deduplicationGroup" type="stringOrStringResourceName"/> + </xsd:complexType> + + <xsd:complexType name="static-safety-source"> + <!-- id must be unique among safety sources --> + <xsd:attribute name="id" type="idOrStringResourceName" use="required"/> + <xsd:attribute name="packageName" type="stringOrStringResourceName"/> + <xsd:attribute name="title" type="runtimeStringResourceName" use="required"/> + <!-- titleForWork is required if profile is set to all_profiles --> + <!-- titleForWork is prohibited if profile is set to primary_profile_only --> + <xsd:attribute name="titleForWork" type="runtimeStringResourceName"/> + <!-- titleForPrivateProfile is required if profile is set to all_profiles --> + <!-- titleForPrivateProfile is prohibited if profile is set to primary_profile_only --> + <xsd:attribute name="titleForPrivateProfile" type="runtimeStringResourceName"/> + <xsd:attribute name="summary" type="runtimeStringResourceName"/> + <xsd:attribute name="intentAction" type="stringOrStringResourceName" use="required"/> + <xsd:attribute name="profile" type="profileOrStringResourceName" use="required"/> + <xsd:attribute name="searchTerms" type="runtimeStringResourceName"/> + </xsd:complexType> + + <xsd:simpleType name="intOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type xsd:int. --> + <xsd:union memberTypes="stringResourceName xsd:int"/> + </xsd:simpleType> + + <xsd:simpleType name="booleanOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type xsd:boolean. --> + <xsd:union memberTypes="stringResourceName xsd:boolean"/> + </xsd:simpleType> + + <xsd:simpleType name="stringOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type xsd:string. --> + <xsd:union memberTypes="stringResourceName xsd:string"/> + </xsd:simpleType> + + <xsd:simpleType name="idOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type xsd:string. --> + <xsd:union memberTypes="stringResourceName id"/> + </xsd:simpleType> + + <xsd:simpleType name="id"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="[0-9a-zA-Z_-]+"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="statelessIconTypeOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type statelessIconType. --> + <xsd:union memberTypes="stringResourceName statelessIconType"/> + </xsd:simpleType> + + <xsd:simpleType name="statelessIconType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="privacy"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="profileOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type profile. --> + <xsd:union memberTypes="stringResourceName profile"/> + </xsd:simpleType> + + <xsd:simpleType name="profile"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="primary_profile_only"/> + <xsd:enumeration value="all_profiles"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="initialDisplayStateOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type initialDisplayState. --> + <xsd:union memberTypes="stringResourceName initialDisplayState"/> + </xsd:simpleType> + + <xsd:simpleType name="initialDisplayState"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="enabled"/> + <xsd:enumeration value="disabled"/> + <xsd:enumeration value="hidden"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="groupTypeOrStringResourceName"> + <!-- String resource names will be resolved only once at parse time. --> + <!-- Locale changes and device config changes will be ignored. --> + <!-- The value of the string resource must be of type groupType. --> + <xsd:union memberTypes="stringResourceName groupType"/> + </xsd:simpleType> + + <xsd:simpleType name="groupType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="stateless"/> + <xsd:enumeration value="stateful"/> + <xsd:enumeration value="hidden"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="runtimeStringResourceName"> + <!-- String resource names will be resolved at runtime whenever the string value is used. --> + <xsd:union memberTypes="stringResourceName"/> + </xsd:simpleType> + + <!-- String resource names will be ignored for any attribute not directly or indirectly marked as stringResourceName. --> + <!-- A stringResourceName is a fully qualified resource name of the form "@package:string/entry". Package is required. --> + <xsd:simpleType name="stringResourceName"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="@([a-z]+\.)*[a-z]+:string/.+"/> + </xsd:restriction> + </xsd:simpleType> + +</xsd:schema> |