Merge "Add CDM system api to check for association presence"
diff --git a/api/system-current.txt b/api/system-current.txt
index fd8fd88..e963560 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1371,6 +1371,14 @@
}
+package android.companion {
+
+ public final class CompanionDeviceManager {
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociated(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+ }
+
+}
+
package android.content {
public class ContentProviderClient implements java.lang.AutoCloseable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 076d32e..466320b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -643,6 +643,14 @@
}
+package android.companion {
+
+ public final class CompanionDeviceManager {
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociated(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+ }
+
+}
+
package android.content {
public final class AutofillOptions implements android.os.Parcelable {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 9cb73f9..28cc1f8 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,7 +21,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.Activity;
import android.app.Application;
import android.app.PendingIntent;
@@ -29,9 +32,11 @@
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
+import android.net.MacAddress;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.util.Log;
@@ -252,6 +257,38 @@
}
}
+ /**
+ * Check if a given package was {@link #associate associated} with a device with given
+ * mac address by given user.
+ *
+ * @param packageName the package to check for
+ * @param macAddress the mac address or BSSID of the device to check for
+ * @param user the user to check for
+ * @return whether a corresponding association record exists
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
+ public boolean isDeviceAssociated(
+ @NonNull String packageName,
+ @NonNull MacAddress macAddress,
+ @NonNull UserHandle user) {
+ if (!checkFeaturePresent()) {
+ return false;
+ }
+ checkNotNull(packageName, "package name cannot be null");
+ checkNotNull(macAddress, "mac address cannot be null");
+ checkNotNull(user, "user cannot be null");
+ try {
+ return mService.isDeviceAssociated(
+ packageName, macAddress.toString(), user.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private boolean checkFeaturePresent() {
boolean featurePresent = mService != null;
if (!featurePresent && DEBUG) {
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 561342e..2e1ff0b 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -39,4 +39,6 @@
boolean hasNotificationAccess(in ComponentName component);
PendingIntent requestNotificationAccess(in ComponentName component);
+
+ boolean isDeviceAssociated(in String packageName, in String macAddress, int userId);
}
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index f9cf23b..4165f20 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -231,6 +231,15 @@
}
/**
+ * Returns whether there exists at least one element in the set for which
+ * condition {@code predicate} is true
+ */
+ public static <T> boolean any(@Nullable Set<T> items,
+ java.util.function.Predicate<T> predicate) {
+ return find(items, predicate) != null;
+ }
+
+ /**
* Returns the first element from the list for which
* condition {@code predicate} is true, or null if there is no such element
*/
@@ -245,6 +254,37 @@
}
/**
+ * Returns the first element from the set for which
+ * condition {@code predicate} is true, or null if there is no such element
+ */
+ public static @Nullable <T> T find(@Nullable Set<T> cur,
+ java.util.function.Predicate<T> predicate) {
+ if (cur == null || predicate == null) return null;
+ int size = cur.size();
+ if (size == 0) return null;
+ try {
+ if (cur instanceof ArraySet) {
+ ArraySet<T> arraySet = (ArraySet<T>) cur;
+ for (int i = 0; i < size; i++) {
+ T item = arraySet.valueAt(i);
+ if (predicate.test(item)) {
+ return item;
+ }
+ }
+ } else {
+ for (T t : cur) {
+ if (predicate.test(t)) {
+ return t;
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw ExceptionUtils.propagate(e);
+ }
+ return null;
+ }
+
+ /**
* Similar to {@link List#add}, but with support for list values of {@code null} and
* {@link Collections#emptyList}
*/
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8a735c7..b357b3e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3553,7 +3553,7 @@
<!-- Allows an application to manage the companion devices.
@hide -->
<permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|wifi" />
<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications.
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 067becb..8f1e156 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -335,6 +335,16 @@
return new ComponentNameSet(setting).contains(component);
}
+ @Override
+ public boolean isDeviceAssociated(String packageName, String macAddress, int userId) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_COMPANION_DEVICES, "isDeviceAssociated");
+
+ return CollectionUtils.any(
+ readAllAssociations(userId, packageName),
+ a -> Objects.equals(a.deviceAddress, macAddress));
+ }
+
private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
checkCallerIsSystemOr(callingPackage);
int userId = getCallingUserId();