From e62958cb98299e43dfcb979527d330c32c9b8258 Mon Sep 17 00:00:00 2001 From: Eugene Susla Date: Fri, 25 Oct 2019 13:30:50 -0700 Subject: [PATCH] Add CDM system api to check for association presence Per agreement with wifi team, wifi stack will call into CDM when wifi connection is requested, treating CDM record similarly to the previously approved networks records, i.e. skipping UI when association exists. Test: atest android.os.cts.CompanionDeviceManagerTest Fixes: 143572863 Change-Id: I28b44076e594fb9357b5a543176d285414ef06f8 --- api/system-current.txt | 8 ++++ api/test-current.txt | 8 ++++ .../companion/CompanionDeviceManager.java | 37 +++++++++++++++++ .../companion/ICompanionDeviceManager.aidl | 2 + .../internal/util/CollectionUtils.java | 40 +++++++++++++++++++ core/res/AndroidManifest.xml | 2 +- .../CompanionDeviceManagerService.java | 10 +++++ 7 files changed, 106 insertions(+), 1 deletion(-) diff --git a/api/system-current.txt b/api/system-current.txt index e6a3e9bf3e8e0..e525a71567c42 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1370,6 +1370,14 @@ package android.bluetooth.le { } +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 a060dfcb83112..5247bd1fa16a6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -640,6 +640,14 @@ package android.bluetooth { } +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 9cb73f931773a..28cc1f8fc107f 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -21,7 +21,10 @@ import static com.android.internal.util.Preconditions.checkNotNull; 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.ComponentName; 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 @@ public final class CompanionDeviceManager { } } + /** + * 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 561342efb3ba2..2e1ff0be85773 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -39,4 +39,6 @@ interface ICompanionDeviceManager { 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 f9cf23b29a696..4165f202998cb 100644 --- a/core/java/com/android/internal/util/CollectionUtils.java +++ b/core/java/com/android/internal/util/CollectionUtils.java @@ -230,6 +230,15 @@ public class CollectionUtils { return find(items, predicate) != null; } + /** + * Returns whether there exists at least one element in the set for which + * condition {@code predicate} is true + */ + public static boolean any(@Nullable Set items, + java.util.function.Predicate 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 @@ -244,6 +253,37 @@ public class CollectionUtils { return null; } + /** + * 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 find(@Nullable Set cur, + java.util.function.Predicate predicate) { + if (cur == null || predicate == null) return null; + int size = cur.size(); + if (size == 0) return null; + try { + if (cur instanceof ArraySet) { + ArraySet arraySet = (ArraySet) 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 11a5062296543..8fa610240d5ac 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3547,7 +3547,7 @@ + android:protectionLevel="signature|wifi" />