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
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 03b8141..1aba97e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4336,10 +4336,12 @@
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 79af65a..d913581 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -559,6 +559,10 @@
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 @@
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 9866cd0..6d33246 100644
--- a/core/java/android/content/UriRelativeFilter.java
+++ b/core/java/android/content/UriRelativeFilter.java
@@ -217,6 +217,15 @@
+ " }";
}
+ /** @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 @@
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 0000000..b251054
--- /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 72c396a..0e49b4f 100644
--- a/core/java/android/content/UriRelativeFilterGroup.java
+++ b/core/java/android/content/UriRelativeFilterGroup.java
@@ -19,6 +19,7 @@
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 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 @@
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 @@
}
}
+ @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 @@
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 0000000..3679e7f
--- /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 0000000..4fb196d
--- /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 77bd147..4dcc517 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.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 @@
}
/**
+ * 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 53205f3..f5af82d 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.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 @@
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 0baaff0..d8713f7a 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -575,6 +575,8 @@
<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 84ef6e5..926e181 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 3f00a9d..7d90240 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.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 @@
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 ac6d795..de464a4 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 @@
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 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 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 @@
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 @@
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 @@
.attribute(ATTR_SIGNATURE, signature)) {
writeStateMap(parentSection, pkgState.getStateMap());
writeUserStates(parentSection, userId, pkgState.getUserStates());
+ writeUriRelativeFilterGroupMap(parentSection, pkgState.getUriRelativeFilterGroupMap());
}
}
@@ -334,6 +384,52 @@
}
}
+ 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 c796b40..305b087 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 @@
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.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 @@
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 @@
}
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 @@
mAttachedPkgStates.put(pkgName, newDomainSetId, new DomainVerificationPkgState(
pkgName, newDomainSetId, hasAutoVerifyDomains, newStateMap, newUserStates,
- null /* signature */));
+ null /* signature */, oldGroups));
}
if (sendBroadcast) {
@@ -1572,8 +1647,6 @@
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 @@
}
// 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 @@
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 @@
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 d71dbbb..46051fe 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 @@
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 com.android.internal.util.DataClass;
+import java.util.List;
import java.util.Objects;
import java.util.UUID;
@@ -77,15 +79,30 @@
@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 @@
*
* 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 @@
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 @@
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 @@
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 @@
"hasAutoVerifyDomains = " + mHasAutoVerifyDomains + ", " +
"stateMap = " + mStateMap + ", " +
"userStates = " + mUserStates + ", " +
- "backupSignatureHash = " + mBackupSignatureHash +
+ "backupSignatureHash = " + mBackupSignatureHash + ", " +
+ "uriRelativeFilterGroupMap = " + mUriRelativeFilterGroupMap +
" }";
}
@@ -273,7 +305,8 @@
&& 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 @@
_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 a8100af..66e0717 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 @@
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.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 @@
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 @@
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 @@
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 65b99c5..4fa4190 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 @@
@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 @@
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"