summaryrefslogtreecommitdiff
path: root/framework-s
diff options
context:
space:
mode:
author Manish Singh <psych@google.com> 2024-02-08 12:55:40 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-02-08 12:55:40 +0000
commitfcba235c4c03c0bf0b58e8b1661be45eec7d57ca (patch)
treef0a2d001ad75140572f9a5d7bf43e0547f362cb6 /framework-s
parenta78527583c737cd4c04535533a9dae6df9f6951b (diff)
parent1103d313bf297370cd948cf4a78d4a3f748ba87e (diff)
Merge changes from topics "ps_safety_center", "sc_biometrics", "sc_private_profile_api" into main
* changes: Add the titleForPrivateProfile API Generalise the code for various profile types - 6 Generalise the code for various profile types - 5 Generalise the code for various profile types - 4 Don't add primary profile in default group summary Generalise the code for various profile types - 3 Generalise the code for various profile types - 2 Generalise the code for various profile types - 1
Diffstat (limited to 'framework-s')
-rw-r--r--framework-s/api/system-current.txt2
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySource.java100
-rw-r--r--framework-s/java/android/safetycenter/config/safety_center_config-v35.xsd223
3 files changed, 318 insertions, 7 deletions
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index 527407bf3..61af606e9 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -571,6 +571,7 @@ package android.safetycenter.config {
method public int getProfile();
method @StringRes public int getSearchTermsResId();
method @StringRes public int getSummaryResId();
+ method @FlaggedApi("com.android.permission.flags.private_profile_title_api") @StringRes public int getTitleForPrivateProfileResId();
method @StringRes public int getTitleForWorkResId();
method @StringRes public int getTitleResId();
method public int getType();
@@ -606,6 +607,7 @@ package android.safetycenter.config {
method @NonNull public android.safetycenter.config.SafetySource.Builder setRefreshOnPageOpenAllowed(boolean);
method @NonNull public android.safetycenter.config.SafetySource.Builder setSearchTermsResId(@StringRes int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setSummaryResId(@StringRes int);
+ method @FlaggedApi("com.android.permission.flags.private_profile_title_api") @NonNull public android.safetycenter.config.SafetySource.Builder setTitleForPrivateProfileResId(@StringRes int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setTitleForWorkResId(@StringRes int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setTitleResId(@StringRes int);
}
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>