diff options
| author | 2024-02-02 00:54:52 -0800 | |
|---|---|---|
| committer | 2024-02-09 13:12:36 -0800 | |
| commit | 53969265f52c07741c3dba5365be231ce3c55817 (patch) | |
| tree | 9efbf5615e9fb7a936290e82d289b801ae9a4d87 | |
| parent | 6b7db2b695acaf68bbfbd2d13bdfe9a97c9fa083 (diff) | |
Add dynamic applinks update API
This API will allow the domian verifier to update the URI relative
filter groups on the domain verification package state. During intent
resolution these group matching will be applied after intent matching.
All existing groups will be cleared when the groups are updated.
Bug: 307557201
Test: atest DomainVerificationManagerApiTest
Test: atest DomainVerificationPersistenceTest
Test: atest CtsDomainVerificationDeviceStandaloneTestCases
Change-Id: I2d60b1f13074cecca106a37399bd4848534703f7
17 files changed, 585 insertions, 26 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 03b8141b45e1..1aba97e0d8d6 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -4336,10 +4336,12 @@ package android.content.pm.verify.domain { public final class DomainVerificationManager { method @Nullable @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public android.content.pm.verify.domain.DomainVerificationInfo getDomainVerificationInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public java.util.SortedSet<android.content.pm.verify.domain.DomainOwner> getOwnersForDomain(@NonNull String); + method @FlaggedApi("android.content.pm.relative_reference_intent_filters") @NonNull public java.util.Map<java.lang.String,java.util.List<android.content.UriRelativeFilterGroup>> getUriRelativeFilterGroups(@NonNull String, @NonNull java.util.List<java.lang.String>); method @NonNull @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public java.util.List<java.lang.String> queryValidVerificationPackageNames(); method @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public void setDomainVerificationLinkHandlingAllowed(@NonNull String, boolean) throws android.content.pm.PackageManager.NameNotFoundException; method @CheckResult @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public int setDomainVerificationStatus(@NonNull java.util.UUID, @NonNull java.util.Set<java.lang.String>, int) throws android.content.pm.PackageManager.NameNotFoundException; method @CheckResult @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public int setDomainVerificationUserSelection(@NonNull java.util.UUID, @NonNull java.util.Set<java.lang.String>, boolean) throws android.content.pm.PackageManager.NameNotFoundException; + method @FlaggedApi("android.content.pm.relative_reference_intent_filters") @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) public void setUriRelativeFilterGroups(@NonNull String, @NonNull java.util.Map<java.lang.String,java.util.List<android.content.UriRelativeFilterGroup>>); field public static final int ERROR_DOMAIN_SET_ID_INVALID = 1; // 0x1 field public static final int ERROR_UNABLE_TO_APPROVE = 3; // 0x3 field public static final int ERROR_UNKNOWN_DOMAIN = 2; // 0x2 diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 79af65a3a3e5..d91358105b0b 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -559,6 +559,10 @@ public class IntentFilter implements Parcelable { sb.append(" sch="); sb.append(mDataSchemes.toString()); } + if (Flags.relativeReferenceIntentFilters() && countUriRelativeFilterGroups() > 0) { + sb.append(" grp="); + sb.append(mUriRelativeFilterGroups.toString()); + } sb.append(" }"); return sb.toString(); } @@ -1807,13 +1811,7 @@ public class IntentFilter implements Parcelable { if (mUriRelativeFilterGroups == null) { return false; } - for (int i = 0; i < mUriRelativeFilterGroups.size(); i++) { - UriRelativeFilterGroup group = mUriRelativeFilterGroups.get(i); - if (group.matchData(data)) { - return group.getAction() == UriRelativeFilterGroup.ACTION_ALLOW; - } - } - return false; + return UriRelativeFilterGroup.matchGroupsToUri(mUriRelativeFilterGroups, data); } /** diff --git a/core/java/android/content/UriRelativeFilter.java b/core/java/android/content/UriRelativeFilter.java index 9866cd0e992a..6d33246ae60d 100644 --- a/core/java/android/content/UriRelativeFilter.java +++ b/core/java/android/content/UriRelativeFilter.java @@ -217,6 +217,15 @@ public final class UriRelativeFilter { + " }"; } + /** @hide */ + public UriRelativeFilterParcel toParcel() { + UriRelativeFilterParcel parcel = new UriRelativeFilterParcel(); + parcel.uriPart = mUriPart; + parcel.patternType = mPatternType; + parcel.filter = mFilter; + return parcel; + } + @Override public boolean equals(@Nullable Object o) { if (this == o) return true; @@ -257,4 +266,11 @@ public final class UriRelativeFilter { mPatternType = Integer.parseInt(parser.getAttributeValue(null, PATTERN_STR)); mFilter = parser.getAttributeValue(null, FILTER_STR); } + + /** @hide */ + public UriRelativeFilter(UriRelativeFilterParcel parcel) { + mUriPart = parcel.uriPart; + mPatternType = parcel.patternType; + mFilter = parcel.filter; + } } diff --git a/core/java/android/content/UriRelativeFilterGroup.aidl b/core/java/android/content/UriRelativeFilterGroup.aidl new file mode 100644 index 000000000000..b251054c967f --- /dev/null +++ b/core/java/android/content/UriRelativeFilterGroup.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2024, 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.content; + +parcelable UriRelativeFilterGroup; diff --git a/core/java/android/content/UriRelativeFilterGroup.java b/core/java/android/content/UriRelativeFilterGroup.java index 72c396a73ec8..0e49b4fe427a 100644 --- a/core/java/android/content/UriRelativeFilterGroup.java +++ b/core/java/android/content/UriRelativeFilterGroup.java @@ -19,6 +19,7 @@ package android.content; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.pm.Flags; import android.net.Uri; import android.os.Parcel; @@ -36,9 +37,11 @@ import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Objects; /** @@ -83,6 +86,40 @@ public final class UriRelativeFilterGroup { private final @Action int mAction; private final ArraySet<UriRelativeFilter> mUriRelativeFilters = new ArraySet<>(); + /** @hide */ + public static boolean matchGroupsToUri(List<UriRelativeFilterGroup> groups, Uri uri) { + for (int i = 0; i < groups.size(); i++) { + if (groups.get(i).matchData(uri)) { + return groups.get(i).getAction() == UriRelativeFilterGroup.ACTION_ALLOW; + } + } + return false; + } + + /** @hide */ + public static List<UriRelativeFilterGroup> parcelsToGroups( + @Nullable List<UriRelativeFilterGroupParcel> parcels) { + List<UriRelativeFilterGroup> groups = new ArrayList<>(); + if (parcels != null) { + for (int i = 0; i < parcels.size(); i++) { + groups.add(new UriRelativeFilterGroup(parcels.get(i))); + } + } + return groups; + } + + /** @hide */ + public static List<UriRelativeFilterGroupParcel> groupsToParcels( + @Nullable List<UriRelativeFilterGroup> groups) { + List<UriRelativeFilterGroupParcel> parcels = new ArrayList<>(); + if (groups != null) { + for (int i = 0; i < groups.size(); i++) { + parcels.add(groups.get(i).toParcel()); + } + } + return parcels; + } + /** * New UriRelativeFilterGroup that matches a Intent data. * @@ -205,6 +242,35 @@ public final class UriRelativeFilterGroup { } } + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + @SuppressWarnings("unchecked") + UriRelativeFilterGroup that = (UriRelativeFilterGroup) o; + if (mAction != that.mAction) return false; + return mUriRelativeFilters.equals(that.mUriRelativeFilters); + } + + @Override + public int hashCode() { + int _hash = 0; + _hash = 31 * _hash + mAction; + _hash = 31 * _hash + java.util.Objects.hashCode(mUriRelativeFilters); + return _hash; + } + + /** @hide */ + public UriRelativeFilterGroupParcel toParcel() { + UriRelativeFilterGroupParcel parcel = new UriRelativeFilterGroupParcel(); + parcel.action = mAction; + parcel.filters = new ArrayList<>(); + for (UriRelativeFilter filter : mUriRelativeFilters) { + parcel.filters.add(filter.toParcel()); + } + return parcel; + } + /** @hide */ UriRelativeFilterGroup(@NonNull Parcel src) { mAction = src.readInt(); @@ -213,4 +279,12 @@ public final class UriRelativeFilterGroup { mUriRelativeFilters.add(new UriRelativeFilter(src)); } } + + /** @hide */ + public UriRelativeFilterGroup(UriRelativeFilterGroupParcel parcel) { + mAction = parcel.action; + for (int i = 0; i < parcel.filters.size(); i++) { + mUriRelativeFilters.add(new UriRelativeFilter(parcel.filters.get(i))); + } + } } diff --git a/core/java/android/content/UriRelativeFilterGroupParcel.aidl b/core/java/android/content/UriRelativeFilterGroupParcel.aidl new file mode 100644 index 000000000000..3679e7f13aa3 --- /dev/null +++ b/core/java/android/content/UriRelativeFilterGroupParcel.aidl @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024, 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.content; + +import android.content.UriRelativeFilterParcel; + +/** + * Class for holding UriRelativeFilterGroup data. + * @hide + */ +parcelable UriRelativeFilterGroupParcel { + int action; + List<UriRelativeFilterParcel> filters; +} diff --git a/core/java/android/content/UriRelativeFilterParcel.aidl b/core/java/android/content/UriRelativeFilterParcel.aidl new file mode 100644 index 000000000000..4fb196d38714 --- /dev/null +++ b/core/java/android/content/UriRelativeFilterParcel.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 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.content; + +/** + * Class for holding UriRelativeFilter data. + * @hide + */ +parcelable UriRelativeFilterParcel { + int uriPart; + int patternType; + String filter; +} diff --git a/core/java/android/content/pm/verify/domain/DomainVerificationManager.java b/core/java/android/content/pm/verify/domain/DomainVerificationManager.java index 77bd14756637..4dcc51729a61 100644 --- a/core/java/android/content/pm/verify/domain/DomainVerificationManager.java +++ b/core/java/android/content/pm/verify/domain/DomainVerificationManager.java @@ -17,6 +17,7 @@ package android.content.pm.verify.domain; import android.annotation.CheckResult; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -25,15 +26,21 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.content.Intent; +import android.content.UriRelativeFilterGroup; +import android.content.UriRelativeFilterGroupParcel; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.UserHandle; +import android.util.ArrayMap; import com.android.internal.util.CollectionUtils; +import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.SortedSet; @@ -156,6 +163,74 @@ public final class DomainVerificationManager { } /** + * Update the URI relative filter groups for a package. All previously existing groups + * will be cleared before the new groups will be applied. + * + * @param packageName The name of the package. + * @param domainToGroupsMap A map of domains to a list of {@link UriRelativeFilterGroup}s that + * should apply to them. Groups for each domain will replace any groups + * provided for that domain in a prior call to this method. Groups will + * be evaluated in the order they are provided. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) + @FlaggedApi(android.content.pm.Flags.FLAG_RELATIVE_REFERENCE_INTENT_FILTERS) + public void setUriRelativeFilterGroups(@NonNull String packageName, + @NonNull Map<String, List<UriRelativeFilterGroup>> domainToGroupsMap) { + Objects.requireNonNull(packageName); + Objects.requireNonNull(domainToGroupsMap); + Bundle bundle = new Bundle(); + for (String domain : domainToGroupsMap.keySet()) { + List<UriRelativeFilterGroup> groups = domainToGroupsMap.get(domain); + bundle.putParcelableList(domain, UriRelativeFilterGroup.groupsToParcels(groups)); + } + try { + mDomainVerificationManager.setUriRelativeFilterGroups(packageName, bundle); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieves a map of a package's verified domains to a list of {@link UriRelativeFilterGroup}s + * that applies to them. + * + * @param packageName The name of the package. + * @param domains List of domains for which to retrieve group matches. + * @return A map of domains to the lists of {@link UriRelativeFilterGroup}s that apply to them. + * @hide + */ + @NonNull + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RELATIVE_REFERENCE_INTENT_FILTERS) + public Map<String, List<UriRelativeFilterGroup>> getUriRelativeFilterGroups( + @NonNull String packageName, + @NonNull List<String> domains) { + Objects.requireNonNull(packageName); + Objects.requireNonNull(domains); + if (domains.isEmpty()) { + return Collections.emptyMap(); + } + try { + Bundle bundle = mDomainVerificationManager.getUriRelativeFilterGroups(packageName, + domains); + ArrayMap<String, List<UriRelativeFilterGroup>> map = new ArrayMap<>(); + if (!bundle.isEmpty()) { + for (String domain : bundle.keySet()) { + List<UriRelativeFilterGroupParcel> parcels = + bundle.getParcelableArrayList(domain, + UriRelativeFilterGroupParcel.class); + map.put(domain, UriRelativeFilterGroup.parcelsToGroups(parcels)); + } + } + return map; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Used to iterate all {@link DomainVerificationInfo} values to do cleanup or retries. This is * usually a heavy workload and should be done infrequently. * diff --git a/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl b/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl index 53205f3ea470..f5af82d36d71 100644 --- a/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl +++ b/core/java/android/content/pm/verify/domain/IDomainVerificationManager.aidl @@ -20,6 +20,8 @@ import android.content.pm.verify.domain.DomainOwner; import android.content.pm.verify.domain.DomainSet; import android.content.pm.verify.domain.DomainVerificationInfo; import android.content.pm.verify.domain.DomainVerificationUserState; +import android.content.UriRelativeFilterGroup; +import android.os.Bundle; import java.util.List; /** @@ -46,4 +48,8 @@ interface IDomainVerificationManager { int setDomainVerificationUserSelection(String domainSetId, in DomainSet domains, boolean enabled, int userId); + + void setUriRelativeFilterGroups(String packageName, in Bundle domainToGroupsBundle); + + Bundle getUriRelativeFilterGroups(String packageName, in List<String> domains); } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 0baaff0bb2fc..d8713f7a13f8 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -575,6 +575,8 @@ applications that come with the platform <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> <!-- Permissions required for CTS test - CtsContactKeysProviderPrivilegedApp --> <permission name="android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS"/> + <!-- Permission required for CTS test - PackageManagerTest --> + <permission name="android.permission.DOMAIN_VERIFICATION_AGENT"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 84ef6e51a00b..926e181943e4 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -917,6 +917,9 @@ <!-- Permissions required for CTS test - GrammaticalInflectionManagerTest --> <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" /> + <!-- Permission required for CTS test - CtsPackageManagerTestCases--> + <uses-permission android:name="android.permission.DOMAIN_VERIFICATION_AGENT" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java index 3f00a9d999aa..7d902401a537 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerStub.java @@ -26,6 +26,7 @@ import android.content.pm.verify.domain.DomainVerificationInfo; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationUserState; import android.content.pm.verify.domain.IDomainVerificationManager; +import android.os.Bundle; import android.os.ServiceSpecificException; import java.util.List; @@ -41,6 +42,27 @@ public class DomainVerificationManagerStub extends IDomainVerificationManager.St mService = service; } + @Override + public void setUriRelativeFilterGroups(@NonNull String packageName, + @NonNull Bundle domainToGroupsBundle) { + try { + mService.setUriRelativeFilterGroups(packageName, domainToGroupsBundle); + } catch (Exception e) { + throw rethrow(e); + } + } + + @NonNull + @Override + public Bundle getUriRelativeFilterGroups( + @NonNull String packageName, @NonNull List<String> domains) { + try { + return mService.getUriRelativeFilterGroups(packageName, domains); + } catch (Exception e) { + throw rethrow(e); + } + } + @NonNull @Override public List<String> queryValidVerificationPackageNames() { diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationPersistence.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationPersistence.java index ac6d79541bc1..de464a4a42bb 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationPersistence.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationPersistence.java @@ -19,6 +19,8 @@ package com.android.server.pm.verify.domain; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.content.UriRelativeFilter; +import android.content.UriRelativeFilterGroup; import android.content.pm.Signature; import android.content.pm.verify.domain.DomainVerificationState; import android.os.UserHandle; @@ -38,7 +40,10 @@ import com.android.server.pm.verify.domain.models.DomainVerificationStateMap; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; +import java.util.List; import java.util.UUID; import java.util.function.Function; @@ -67,6 +72,13 @@ public class DomainVerificationPersistence { public static final String TAG_DOMAIN = "domain"; public static final String ATTR_NAME = "name"; public static final String ATTR_STATE = "state"; + public static final String TAG_URI_RELATIVE_FILTER_GROUPS = "uri-relative-filter-groups"; + public static final String TAG_URI_RELATIVE_FILTER_GROUP = "uri-relative-filter-group"; + public static final String ATTR_ACTION = "action"; + public static final String TAG_URI_RELATIVE_FILTER = "uri-relative-filter"; + public static final String ATTR_URI_PART = "uri-part"; + public static final String ATTR_PATTERN_TYPE = "pattern-type"; + public static final String ATTR_FILTER = "filter"; /** * @param pkgNameToSignature Converts package name to a string representation of its signature. @@ -176,6 +188,7 @@ public class DomainVerificationPersistence { final ArrayMap<String, Integer> stateMap = new ArrayMap<>(); final SparseArray<DomainVerificationInternalUserState> userStates = new SparseArray<>(); + final ArrayMap<String, List<UriRelativeFilterGroup>> groupMap = new ArrayMap<>(); SettingsXml.ChildSection child = section.children(); while (child.moveToNext()) { @@ -186,11 +199,47 @@ public class DomainVerificationPersistence { case TAG_USER_STATES: readUserStates(child, userStates); break; + case TAG_URI_RELATIVE_FILTER_GROUPS: + readUriRelativeFilterGroups(child, groupMap); + break; } } return new DomainVerificationPkgState(packageName, id, hasAutoVerifyDomains, stateMap, - userStates, signature); + userStates, signature, groupMap); + } + + private static void readUriRelativeFilterGroups(@NonNull SettingsXml.ReadSection section, + @NonNull ArrayMap<String, List<UriRelativeFilterGroup>> groupMap) { + SettingsXml.ChildSection child = section.children(); + while (child.moveToNext(TAG_DOMAIN)) { + String domain = child.getString(ATTR_NAME); + groupMap.put(domain, createUriRelativeFilterGroupsFromXml(child)); + } + } + + private static ArrayList<UriRelativeFilterGroup> createUriRelativeFilterGroupsFromXml( + @NonNull SettingsXml.ReadSection section) { + SettingsXml.ChildSection child = section.children(); + ArrayList<UriRelativeFilterGroup> groups = new ArrayList<>(); + while (child.moveToNext(TAG_URI_RELATIVE_FILTER_GROUP)) { + UriRelativeFilterGroup group = new UriRelativeFilterGroup(section.getInt(ATTR_ACTION)); + readUriRelativeFiltersFromXml(child, group); + groups.add(group); + } + return groups; + } + + private static void readUriRelativeFiltersFromXml( + @NonNull SettingsXml.ReadSection section, UriRelativeFilterGroup group) { + SettingsXml.ChildSection child = section.children(); + while (child.moveToNext(TAG_URI_RELATIVE_FILTER)) { + String filter = child.getString(ATTR_FILTER); + if (filter != null) { + group.addUriRelativeFilter(new UriRelativeFilter(child.getInt(ATTR_URI_PART), + child.getInt(ATTR_PATTERN_TYPE), filter)); + } + } } private static void readUserStates(@NonNull SettingsXml.ReadSection section, @@ -236,6 +285,7 @@ public class DomainVerificationPersistence { .attribute(ATTR_SIGNATURE, signature)) { writeStateMap(parentSection, pkgState.getStateMap()); writeUserStates(parentSection, userId, pkgState.getUserStates()); + writeUriRelativeFilterGroupMap(parentSection, pkgState.getUriRelativeFilterGroupMap()); } } @@ -334,6 +384,52 @@ public class DomainVerificationPersistence { } } + private static void writeUriRelativeFilterGroupMap( + @NonNull SettingsXml.WriteSection parentSection, + @NonNull ArrayMap<String, List<UriRelativeFilterGroup>> groupMap) throws IOException { + if (groupMap.isEmpty()) { + return; + } + try (SettingsXml.WriteSection section = + parentSection.startSection(TAG_URI_RELATIVE_FILTER_GROUPS)) { + for (int i = 0; i < groupMap.size(); i++) { + writeUriRelativeFilterGroups(section, groupMap.keyAt(i), groupMap.valueAt(i)); + } + } + } + + private static void writeUriRelativeFilterGroups( + @NonNull SettingsXml.WriteSection parentSection, @NonNull String domain, + @NonNull List<UriRelativeFilterGroup> groups) throws IOException { + if (groups.isEmpty()) { + return; + } + try (SettingsXml.WriteSection section = + parentSection.startSection(TAG_DOMAIN) + .attribute(ATTR_NAME, domain)) { + for (int i = 0; i < groups.size(); i++) { + writeUriRelativeFilterGroup(section, groups.get(i)); + } + } + } + + private static void writeUriRelativeFilterGroup( + @NonNull SettingsXml.WriteSection parentSection, + @NonNull UriRelativeFilterGroup group) throws IOException { + try (SettingsXml.WriteSection section = + parentSection.startSection(TAG_URI_RELATIVE_FILTER_GROUP) + .attribute(ATTR_ACTION, group.getAction())) { + Iterator<UriRelativeFilter> it = group.getUriRelativeFilters().iterator(); + while (it.hasNext()) { + UriRelativeFilter filter = it.next(); + section.startSection(TAG_URI_RELATIVE_FILTER) + .attribute(ATTR_URI_PART, filter.getUriPart()) + .attribute(ATTR_PATTERN_TYPE, filter.getPatternType()) + .attribute(ATTR_FILTER, filter.getFilter()).finish(); + } + } + } + public static class ReadResult { @NonNull diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java index c796b40f11bf..305b087190d6 100644 --- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java +++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java @@ -19,14 +19,19 @@ package com.android.server.pm.verify.domain; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; +import android.Manifest; import android.annotation.CheckResult; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.compat.annotation.ChangeId; import android.content.Context; import android.content.Intent; +import android.content.UriRelativeFilterGroup; +import android.content.UriRelativeFilterGroupParcel; +import android.content.pm.Flags; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -38,6 +43,8 @@ import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationState; import android.content.pm.verify.domain.DomainVerificationUserState; import android.content.pm.verify.domain.IDomainVerificationManager; +import android.net.Uri; +import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; @@ -223,6 +230,72 @@ public class DomainVerificationService extends SystemService mProxy = proxy; } + /** + * Update the URI relative filter groups for a package's verified domains. All previously + * existing groups will be cleared before the new groups will be applied. + */ + @RequiresPermission(Manifest.permission.DOMAIN_VERIFICATION_AGENT) + public void setUriRelativeFilterGroups(@NonNull String packageName, + @NonNull Bundle bundle) + throws NameNotFoundException { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.DOMAIN_VERIFICATION_AGENT, + "Caller " + mConnection.getCallingUid() + " does not hold " + + android.Manifest.permission.DOMAIN_VERIFICATION_AGENT); + if (bundle.isEmpty()) { + return; + } + synchronized (mLock) { + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState == null) { + throw DomainVerificationUtils.throwPackageUnavailable(packageName); + } + Map<String, List<UriRelativeFilterGroup>> domainToGroupsMap = + pkgState.getUriRelativeFilterGroupMap(); + for (String domain : bundle.keySet()) { + ArrayList<UriRelativeFilterGroupParcel> parcels = + bundle.getParcelableArrayList(domain, UriRelativeFilterGroupParcel.class); + domainToGroupsMap.put(domain, UriRelativeFilterGroup.parcelsToGroups(parcels)); + } + } + } + + /** + * Retrieve the current URI relative filter groups for a package's verified domain. + */ + @NonNull + public Bundle getUriRelativeFilterGroups(@NonNull String packageName, + @NonNull List<String> domains) { + Bundle bundle = new Bundle(); + synchronized (mLock) { + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState != null) { + Map<String, List<UriRelativeFilterGroup>> map = + pkgState.getUriRelativeFilterGroupMap(); + for (int i = 0; i < domains.size(); i++) { + List<UriRelativeFilterGroup> groups = map.get(domains.get(i)); + bundle.putParcelableList(domains.get(i), + UriRelativeFilterGroup.groupsToParcels(groups)); + } + } + } + return bundle; + } + + @NonNull + private List<UriRelativeFilterGroup> getUriRelativeFilterGroups(@NonNull String packageName, + @NonNull String domain) { + List<UriRelativeFilterGroup> groups = Collections.emptyList(); + synchronized (mLock) { + DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName); + if (pkgState != null) { + groups = pkgState.getUriRelativeFilterGroupMap().getOrDefault(domain, + Collections.emptyList()); + } + } + return groups; + } + @NonNull public List<String> queryValidVerificationPackageNames() { mEnforcer.assertApprovedVerifier(mConnection.getCallingUid(), mProxy); @@ -891,6 +964,8 @@ public class DomainVerificationService extends SystemService } ArrayMap<String, Integer> oldStateMap = oldPkgState.getStateMap(); + ArrayMap<String, List<UriRelativeFilterGroup>> oldGroups = + oldPkgState.getUriRelativeFilterGroupMap(); ArraySet<String> newAutoVerifyDomains = mCollector.collectValidAutoVerifyDomains(newPkg); int newDomainsSize = newAutoVerifyDomains.size(); @@ -941,7 +1016,7 @@ public class DomainVerificationService extends SystemService mAttachedPkgStates.put(pkgName, newDomainSetId, new DomainVerificationPkgState( pkgName, newDomainSetId, hasAutoVerifyDomains, newStateMap, newUserStates, - null /* signature */)); + null /* signature */, oldGroups)); } if (sendBroadcast) { @@ -1572,8 +1647,6 @@ public class DomainVerificationService extends SystemService public Pair<List<ResolveInfo>, Integer> filterToApprovedApp(@NonNull Intent intent, @NonNull List<ResolveInfo> infos, @UserIdInt int userId, @NonNull Function<String, PackageStateInternal> pkgSettingFunction) { - String domain = intent.getData().getHost(); - // Collect valid infos ArrayMap<ResolveInfo, Integer> infoApprovals = new ArrayMap<>(); int infosSize = infos.size(); @@ -1586,7 +1659,7 @@ public class DomainVerificationService extends SystemService } // Find all approval levels - int highestApproval = fillMapWithApprovalLevels(infoApprovals, domain, userId, + int highestApproval = fillMapWithApprovalLevels(infoApprovals, intent.getData(), userId, pkgSettingFunction); if (highestApproval <= APPROVAL_LEVEL_NONE) { return Pair.create(emptyList(), highestApproval); @@ -1623,12 +1696,23 @@ public class DomainVerificationService extends SystemService return Pair.create(finalList, highestApproval); } + private boolean matchUriRelativeFilterGroups(Uri uri, String pkgName) { + if (uri.getHost() == null) { + return false; + } + List<UriRelativeFilterGroup> groups = getUriRelativeFilterGroups(pkgName, uri.getHost()); + if (groups.isEmpty()) { + return true; + } + return UriRelativeFilterGroup.matchGroupsToUri(groups, uri); + } + /** * @return highest approval level found */ @ApprovalLevel private int fillMapWithApprovalLevels(@NonNull ArrayMap<ResolveInfo, Integer> inputMap, - @NonNull String domain, @UserIdInt int userId, + @NonNull Uri uri, @UserIdInt int userId, @NonNull Function<String, PackageStateInternal> pkgSettingFunction) { int highestApproval = APPROVAL_LEVEL_NONE; int size = inputMap.size(); @@ -1641,12 +1725,13 @@ public class DomainVerificationService extends SystemService ResolveInfo info = inputMap.keyAt(index); final String packageName = info.getComponentInfo().packageName; PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName); - if (pkgSetting == null) { + if (pkgSetting == null || (Flags.relativeReferenceIntentFilters() + && !matchUriRelativeFilterGroups(uri, packageName))) { fillInfoMapForSamePackage(inputMap, packageName, APPROVAL_LEVEL_NONE); continue; } - int approval = approvalLevelForDomain(pkgSetting, domain, false, userId, DEBUG_APPROVAL, - domain); + int approval = approvalLevelForDomain(pkgSetting, uri.getHost(), false, userId, + DEBUG_APPROVAL, uri.getHost()); highestApproval = Math.max(highestApproval, approval); fillInfoMapForSamePackage(inputMap, packageName, approval); } diff --git a/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java b/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java index d71dbbb5d53b..46051fe3d782 100644 --- a/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java +++ b/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java @@ -19,6 +19,7 @@ package com.android.server.pm.verify.domain.models; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.content.UriRelativeFilterGroup; import android.content.pm.Signature; import android.content.pm.verify.domain.DomainVerificationState; import android.util.ArrayMap; @@ -26,6 +27,7 @@ import android.util.SparseArray; import com.android.internal.util.DataClass; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -77,15 +79,30 @@ public class DomainVerificationPkgState { @Nullable private final String mBackupSignatureHash; + /** + * List of {@link UriRelativeFilterGroup} for filtering domains. + */ + @NonNull + private final ArrayMap<String, List<UriRelativeFilterGroup>> mUriRelativeFilterGroupMap; + public DomainVerificationPkgState(@NonNull String packageName, @NonNull UUID id, boolean hasAutoVerifyDomains) { - this(packageName, id, hasAutoVerifyDomains, new ArrayMap<>(0), new SparseArray<>(0), null); + this(packageName, id, hasAutoVerifyDomains, new ArrayMap<>(0), new SparseArray<>(0), null, + new ArrayMap<>()); } public DomainVerificationPkgState(@NonNull DomainVerificationPkgState pkgState, @NonNull UUID id, boolean hasAutoVerifyDomains) { this(pkgState.getPackageName(), id, hasAutoVerifyDomains, pkgState.getStateMap(), - pkgState.getUserStates(), null); + pkgState.getUserStates(), null, new ArrayMap<>()); + } + + public DomainVerificationPkgState(@NonNull String packageName, @NonNull UUID id, + boolean hasAutoVerifyDomains, @NonNull ArrayMap<String, Integer> stateMap, + @NonNull SparseArray<DomainVerificationInternalUserState> userStates, + @Nullable String backupSignatureHash) { + this(packageName, id, hasAutoVerifyDomains, stateMap, userStates, backupSignatureHash, + new ArrayMap<>()); } @Nullable @@ -158,6 +175,8 @@ public class DomainVerificationPkgState { * * It's assumed the domain verification agent will eventually re-verify this domain * and revoke if necessary. + * @param uriRelativeFilterGroupMap + * List of {@link UriRelativeFilterGroup} for filtering domains. */ @DataClass.Generated.Member public DomainVerificationPkgState( @@ -166,7 +185,8 @@ public class DomainVerificationPkgState { boolean hasAutoVerifyDomains, @NonNull ArrayMap<String,Integer> stateMap, @NonNull SparseArray<DomainVerificationInternalUserState> userStates, - @Nullable String backupSignatureHash) { + @Nullable String backupSignatureHash, + @NonNull ArrayMap<String,List<UriRelativeFilterGroup>> uriRelativeFilterGroupMap) { this.mPackageName = packageName; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mPackageName); @@ -181,6 +201,9 @@ public class DomainVerificationPkgState { com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mUserStates); this.mBackupSignatureHash = backupSignatureHash; + this.mUriRelativeFilterGroupMap = uriRelativeFilterGroupMap; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mUriRelativeFilterGroupMap); // onConstructed(); // You can define this method to get a callback } @@ -239,6 +262,14 @@ public class DomainVerificationPkgState { return mBackupSignatureHash; } + /** + * List of {@link UriRelativeFilterGroup} for filtering domains. + */ + @DataClass.Generated.Member + public @NonNull ArrayMap<String,List<UriRelativeFilterGroup>> getUriRelativeFilterGroupMap() { + return mUriRelativeFilterGroupMap; + } + @Override @DataClass.Generated.Member public String toString() { @@ -251,7 +282,8 @@ public class DomainVerificationPkgState { "hasAutoVerifyDomains = " + mHasAutoVerifyDomains + ", " + "stateMap = " + mStateMap + ", " + "userStates = " + mUserStates + ", " + - "backupSignatureHash = " + mBackupSignatureHash + + "backupSignatureHash = " + mBackupSignatureHash + ", " + + "uriRelativeFilterGroupMap = " + mUriRelativeFilterGroupMap + " }"; } @@ -273,7 +305,8 @@ public class DomainVerificationPkgState { && mHasAutoVerifyDomains == that.mHasAutoVerifyDomains && Objects.equals(mStateMap, that.mStateMap) && userStatesEquals(that.mUserStates) - && Objects.equals(mBackupSignatureHash, that.mBackupSignatureHash); + && Objects.equals(mBackupSignatureHash, that.mBackupSignatureHash) + && Objects.equals(mUriRelativeFilterGroupMap, that.mUriRelativeFilterGroupMap); } @Override @@ -289,14 +322,15 @@ public class DomainVerificationPkgState { _hash = 31 * _hash + Objects.hashCode(mStateMap); _hash = 31 * _hash + userStatesHashCode(); _hash = 31 * _hash + Objects.hashCode(mBackupSignatureHash); + _hash = 31 * _hash + Objects.hashCode(mUriRelativeFilterGroupMap); return _hash; } @DataClass.Generated( - time = 1617315369614L, + time = 1707351734724L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java", - inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate @android.annotation.NonNull java.util.UUID mId\nprivate final boolean mHasAutoVerifyDomains\nprivate final @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.lang.Integer> mStateMap\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState> mUserStates\nprivate final @android.annotation.Nullable java.lang.String mBackupSignatureHash\npublic @android.annotation.Nullable com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState getUserState(int)\npublic @android.annotation.Nullable com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState getOrCreateUserState(int)\npublic void removeUser(int)\npublic void removeAllUsers()\nprivate int userStatesHashCode()\nprivate boolean userStatesEquals(android.util.SparseArray<com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState>)\nclass DomainVerificationPkgState extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)") + inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.util.UUID mId\nprivate final boolean mHasAutoVerifyDomains\nprivate final @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.lang.Integer> mStateMap\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState> mUserStates\nprivate final @android.annotation.Nullable java.lang.String mBackupSignatureHash\nprivate final @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.util.List<android.content.UriRelativeFilterGroup>> mUriRelativeFilterGroupMap\npublic @android.annotation.Nullable com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState getUserState(int)\npublic @android.annotation.Nullable com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState getOrCreateUserState(int)\npublic void removeUser(int)\npublic void removeAllUsers()\nprivate int userStatesHashCode()\nprivate boolean userStatesEquals(android.util.SparseArray<com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState>)\nclass DomainVerificationPkgState extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)") @Deprecated private void __metadata() {} diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt index a8100afc4ac4..66e07175e7f5 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt @@ -18,6 +18,10 @@ package com.android.server.pm.test.verify.domain import android.content.Context import android.content.Intent +import android.content.UriRelativeFilter +import android.content.UriRelativeFilterGroup +import android.content.UriRelativeFilterGroupParcel +import android.content.pm.Flags import android.content.pm.PackageManager import android.content.pm.verify.domain.DomainOwner import android.content.pm.verify.domain.DomainVerificationInfo @@ -25,8 +29,10 @@ import android.content.pm.verify.domain.DomainVerificationManager import android.content.pm.verify.domain.DomainVerificationUserState import android.content.pm.verify.domain.IDomainVerificationManager import android.os.Build -import android.os.PatternMatcher +import android.os.Bundle +import android.os.PatternMatcher.PATTERN_LITERAL import android.os.Process +import android.platform.test.annotations.RequiresFlagsEnabled import android.util.ArraySet import android.util.SparseArray import com.android.internal.pm.parsing.pkg.AndroidPackageInternal @@ -68,6 +74,63 @@ class DomainVerificationManagerApiTest { private val DOMAIN_4 = "four.$DOMAIN_BASE" } + @RequiresFlagsEnabled(Flags.FLAG_RELATIVE_REFERENCE_INTENT_FILTERS) + @Test + fun updateUriRelativeFilterGroups() { + val pkgWithDomains = mockPkgState(PKG_ONE, UUID_ONE, listOf(DOMAIN_1, DOMAIN_2)) + val service = makeService(pkgWithDomains).apply { + addPackages(pkgWithDomains) + } + + val bundle = service.getUriRelativeFilterGroups(PKG_ONE, listOf(DOMAIN_1, DOMAIN_2)) + assertThat(bundle.keySet()).containsExactlyElementsIn(listOf(DOMAIN_1, DOMAIN_2)) + assertThat(bundle.getParcelableArrayList(DOMAIN_1, UriRelativeFilterGroup::class.java)) + .isEmpty() + assertThat(bundle.getParcelableArrayList(DOMAIN_2, UriRelativeFilterGroup::class.java)) + .isEmpty() + + val pathGroup = UriRelativeFilterGroup(UriRelativeFilterGroup.ACTION_ALLOW) + pathGroup.addUriRelativeFilter( + UriRelativeFilter(UriRelativeFilter.PATH, PATTERN_LITERAL, "path") + ) + val queryGroup = UriRelativeFilterGroup(UriRelativeFilterGroup.ACTION_BLOCK) + queryGroup.addUriRelativeFilter( + UriRelativeFilter(UriRelativeFilter.QUERY, PATTERN_LITERAL, "query") + ) + val fragmentGroup = UriRelativeFilterGroup(UriRelativeFilterGroup.ACTION_ALLOW) + fragmentGroup.addUriRelativeFilter( + UriRelativeFilter(UriRelativeFilter.FRAGMENT, PATTERN_LITERAL, "fragment") + ) + + assertGroups(service, arrayListOf(pathGroup)) + assertGroups(service, arrayListOf(queryGroup, pathGroup)) + assertGroups(service, arrayListOf(queryGroup, fragmentGroup, pathGroup)) + } + + private fun assertGroups( + service: DomainVerificationService, + groups: List<UriRelativeFilterGroup> + ) { + val bundle = Bundle() + bundle.putParcelableList(DOMAIN_1, UriRelativeFilterGroup.groupsToParcels(groups)) + service.setUriRelativeFilterGroups(PKG_ONE, bundle) + val fetchedBundle = service.getUriRelativeFilterGroups(PKG_ONE, listOf(DOMAIN_1)) + assertThat(fetchedBundle.keySet()).containsExactlyElementsIn(bundle.keySet()) + assertThat( + UriRelativeFilterGroup.parcelsToGroups( + fetchedBundle.getParcelableArrayList( + DOMAIN_1, + UriRelativeFilterGroupParcel::class.java) + ) + ).containsExactlyElementsIn( + UriRelativeFilterGroup.parcelsToGroups( + bundle.getParcelableArrayList( + DOMAIN_1, + UriRelativeFilterGroupParcel::class.java) + ) + ).inOrder() + } + @Test fun queryValidVerificationPackageNames() { val pkgWithDomains = mockPkgState(PKG_ONE, UUID_ONE, listOf(DOMAIN_1, DOMAIN_2)) @@ -484,6 +547,7 @@ class DomainVerificationManagerApiTest { DomainVerificationService(mockThrowOnUnmocked { // Assume the test has every permission necessary whenever(enforcePermission(anyString(), anyInt(), anyInt(), anyString())) + whenever(enforceCallingOrSelfPermission(anyString(), anyString())) whenever(checkPermission(anyString(), anyInt(), anyInt())) { PackageManager.PERMISSION_GRANTED } @@ -539,7 +603,7 @@ class DomainVerificationManagerApiTest { addCategory(Intent.CATEGORY_DEFAULT) addDataScheme("http") addDataScheme("https") - addDataPath("/sub", PatternMatcher.PATTERN_LITERAL) + addDataPath("/sub", PATTERN_LITERAL) addDataAuthority(it, null) } } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPersistenceTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPersistenceTest.kt index 65b99c524e0e..4fa4190c847b 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPersistenceTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPersistenceTest.kt @@ -16,7 +16,12 @@ package com.android.server.pm.test.verify.domain +import android.content.UriRelativeFilter +import android.content.UriRelativeFilter.PATH +import android.content.UriRelativeFilterGroup +import android.content.UriRelativeFilterGroup.ACTION_ALLOW import android.content.pm.verify.domain.DomainVerificationState +import android.os.PatternMatcher.PATTERN_LITERAL import android.os.UserHandle import android.util.ArrayMap import android.util.SparseArray @@ -157,7 +162,7 @@ class DomainVerificationPersistenceTest { @Test fun writeStateSignatureIfFunctionReturnsNull() { - val (attached, pending, restored) = mockWriteValues { "SIGNATURE_$it" } + val (attached, pending, restored) = mockWriteValues { "SIGNATURE_$it" } val file = tempFolder.newFile().writeXml { DomainVerificationPersistence.writeToXml(it, attached, pending, restored, UserHandle.USER_ALL) { null } @@ -313,6 +318,9 @@ class DomainVerificationPersistenceTest { addHosts(setOf("$packageName-user.com")) isLinkHandlingAllowed = true } + val group = UriRelativeFilterGroup(ACTION_ALLOW) + group.addUriRelativeFilter(UriRelativeFilter(PATH, PATTERN_LITERAL, "test")) + uriRelativeFilterGroupMap.put("example.com", listOf(group)) } private fun pkgName(id: Int) = "$PKG_PREFIX.pkg$id" |