From 991e8eed4f63ea282564956eebce59887b6ac16e Mon Sep 17 00:00:00 2001 From: Eugene Susla Date: Thu, 9 Jul 2020 17:51:20 -0700 Subject: [PATCH] Expose syspem API for querying CDM associations We want to restrict some BT capabilities(e.g. unpair device) to only the package's associated device. Since BT will become a mainline module, this needs to be exposed as a @SystemApi Test: ateast android.os.cts.CompanionDeviceManagerTest#testGetAllAssociations Bug: 165951651 Change-Id: Iab0da9352671e0b82ac855f91a6625c810946d17 --- core/java/android/companion/Association.java | 102 +++++++++++------- .../companion/CompanionDeviceManager.java | 18 ++++ .../companion/ICompanionDeviceManager.aidl | 3 + .../CompanionDeviceManagerService.java | 35 +++--- 4 files changed, 106 insertions(+), 52 deletions(-) diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/Association.java index 3fa6a3e76634b..06a3f2f08bab6 100644 --- a/core/java/android/companion/Association.java +++ b/core/java/android/companion/Association.java @@ -17,6 +17,7 @@ package android.companion; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.os.Parcel; import android.os.Parcelable; @@ -30,17 +31,21 @@ import java.util.Objects; * * @hide */ -@DataClass(genEqualsHashCode = true, genToString = true) -public class Association implements Parcelable { +@DataClass(genEqualsHashCode = true, genToString = true, genHiddenConstructor = true) +public final class Association implements Parcelable { - public final int userId; - public final @NonNull String deviceAddress; - public final @NonNull String companionAppPackage; + private final @UserIdInt int mUserId; + private final @NonNull String mDeviceMacAddress; + private final @NonNull String mPackageName; + + /** @hide */ + public int getUserId() { + return mUserId; + } - - // Code below generated by codegen v1.0.13. + // Code below generated by codegen v1.0.15. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -53,22 +58,39 @@ public class Association implements Parcelable { //@formatter:off + /** + * Creates a new Association. + * + * @hide + */ @DataClass.Generated.Member public Association( - int userId, - @NonNull String deviceAddress, - @NonNull String companionAppPackage) { - this.userId = userId; - this.deviceAddress = deviceAddress; + @UserIdInt int userId, + @NonNull String deviceMacAddress, + @NonNull String packageName) { + this.mUserId = userId; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, deviceAddress); - this.companionAppPackage = companionAppPackage; + UserIdInt.class, null, mUserId); + this.mDeviceMacAddress = deviceMacAddress; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, companionAppPackage); + NonNull.class, null, mDeviceMacAddress); + this.mPackageName = packageName; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mPackageName); // onConstructed(); // You can define this method to get a callback } + @DataClass.Generated.Member + public @NonNull String getDeviceMacAddress() { + return mDeviceMacAddress; + } + + @DataClass.Generated.Member + public @NonNull String getPackageName() { + return mPackageName; + } + @Override @DataClass.Generated.Member public String toString() { @@ -76,9 +98,9 @@ public class Association implements Parcelable { // String fieldNameToString() { ... } return "Association { " + - "userId = " + userId + ", " + - "deviceAddress = " + deviceAddress + ", " + - "companionAppPackage = " + companionAppPackage + + "userId = " + mUserId + ", " + + "deviceMacAddress = " + mDeviceMacAddress + ", " + + "packageName = " + mPackageName + " }"; } @@ -95,9 +117,9 @@ public class Association implements Parcelable { Association that = (Association) o; //noinspection PointlessBooleanExpression return true - && userId == that.userId - && Objects.equals(deviceAddress, that.deviceAddress) - && Objects.equals(companionAppPackage, that.companionAppPackage); + && mUserId == that.mUserId + && Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress) + && Objects.equals(mPackageName, that.mPackageName); } @Override @@ -107,9 +129,9 @@ public class Association implements Parcelable { // int fieldNameHashCode() { ... } int _hash = 1; - _hash = 31 * _hash + userId; - _hash = 31 * _hash + Objects.hashCode(deviceAddress); - _hash = 31 * _hash + Objects.hashCode(companionAppPackage); + _hash = 31 * _hash + mUserId; + _hash = 31 * _hash + Objects.hashCode(mDeviceMacAddress); + _hash = 31 * _hash + Objects.hashCode(mPackageName); return _hash; } @@ -119,9 +141,9 @@ public class Association implements Parcelable { // You can override field parcelling by defining methods like: // void parcelFieldName(Parcel dest, int flags) { ... } - dest.writeInt(userId); - dest.writeString(deviceAddress); - dest.writeString(companionAppPackage); + dest.writeInt(mUserId); + dest.writeString(mDeviceMacAddress); + dest.writeString(mPackageName); } @Override @@ -131,21 +153,23 @@ public class Association implements Parcelable { /** @hide */ @SuppressWarnings({"unchecked", "RedundantCast"}) @DataClass.Generated.Member - protected Association(@NonNull Parcel in) { + /* package-private */ Association(@NonNull Parcel in) { // You can override field unparcelling by defining methods like: // static FieldType unparcelFieldName(Parcel in) { ... } - int _userId = in.readInt(); - String _deviceAddress = in.readString(); - String _companionAppPackage = in.readString(); + int userId = in.readInt(); + String deviceMacAddress = in.readString(); + String packageName = in.readString(); - this.userId = _userId; - this.deviceAddress = _deviceAddress; + this.mUserId = userId; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, deviceAddress); - this.companionAppPackage = _companionAppPackage; + UserIdInt.class, null, mUserId); + this.mDeviceMacAddress = deviceMacAddress; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, companionAppPackage); + NonNull.class, null, mDeviceMacAddress); + this.mPackageName = packageName; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mPackageName); // onConstructed(); // You can define this method to get a callback } @@ -165,10 +189,10 @@ public class Association implements Parcelable { }; @DataClass.Generated( - time = 1573767103332L, - codegenVersion = "1.0.13", + time = 1599083149942L, + codegenVersion = "1.0.15", sourceFile = "frameworks/base/core/java/android/companion/Association.java", - inputSignatures = "public final int userId\npublic final @android.annotation.NonNull java.lang.String deviceAddress\npublic final @android.annotation.NonNull java.lang.String companionAppPackage\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)") + inputSignatures = "private final @android.annotation.UserIdInt int mUserId\nprivate final @android.annotation.NonNull java.lang.String mDeviceMacAddress\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic int getUserId()\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)") @Deprecated private void __metadata() {} diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 591a714bfb930..da4980bba3d09 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -305,6 +305,24 @@ public final class CompanionDeviceManager { } } + /** + * Gets all package-device {@link Association}s for the current user. + * + * @return the associations list + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES) + public @NonNull List getAllAssociations() { + if (!checkFeaturePresent()) { + return Collections.emptyList(); + } + try { + return mService.getAssociationsForUser(mContext.getUser().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 b323f58aa8270..bcb9be80e6a44 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -18,6 +18,7 @@ package android.companion; import android.app.PendingIntent; import android.companion.IFindDeviceCallback; +import android.companion.Association; import android.companion.AssociationRequest; import android.content.ComponentName; @@ -35,6 +36,8 @@ interface ICompanionDeviceManager { in String callingPackage); List getAssociations(String callingPackage, int userId); + List getAssociationsForUser(int userId); + void disassociate(String deviceMacAddress, String callingPackage); boolean hasNotificationAccess(in ComponentName component); diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 7b9728cb4f080..45cbad181e04f 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -85,7 +85,6 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import com.android.server.wm.ActivityTaskManagerInternal; import org.xmlpull.v1.XmlPullParser; @@ -170,7 +169,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind public void onPackageRemoved(String packageName, int uid) { updateAssociations( as -> CollectionUtils.filter(as, - a -> !Objects.equals(a.companionAppPackage, packageName)), + a -> !Objects.equals(a.getPackageName(), packageName)), getChangingUserId()); } @@ -199,7 +198,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } Set companionAppPackages = new HashSet<>(); for (Association association : associations) { - companionAppPackages.add(association.companionAppPackage); + companionAppPackages.add(association.getPackageName()); } ActivityTaskManagerInternal atmInternal = LocalServices.getService( ActivityTaskManagerInternal.class); @@ -229,10 +228,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } for (Association a : associations) { try { - int uid = pm.getPackageUidAsUser(a.companionAppPackage, userId); - exemptFromAutoRevoke(a.companionAppPackage, uid); + int uid = pm.getPackageUidAsUser(a.getPackageName(), userId); + exemptFromAutoRevoke(a.getPackageName(), uid); } catch (PackageManager.NameNotFoundException e) { - Log.w(LOG_TAG, "Unknown companion package: " + a.companionAppPackage, e); + Log.w(LOG_TAG, "Unknown companion package: " + a.getPackageName(), e); } } } finally { @@ -344,7 +343,17 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } return new ArrayList<>(CollectionUtils.map( readAllAssociations(userId, callingPackage), - a -> a.deviceAddress)); + a -> a.getDeviceMacAddress())); + } + + @Override + public List getAssociationsForUser(int userId) { + if (!callerCanManageCompanionDevices()) { + throw new SecurityException("Caller must hold " + + android.Manifest.permission.MANAGE_COMPANION_DEVICES); + } + + return new ArrayList<>(readAllAssociations(userId, null /* packageFilter */)); } //TODO also revoke notification access @@ -429,7 +438,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return CollectionUtils.any( readAllAssociations(userId, packageName), - a -> Objects.equals(a.deviceAddress, macAddress)); + a -> Objects.equals(a.getDeviceMacAddress(), macAddress)); } private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { @@ -479,7 +488,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind void addAssociation(Association association) { updateSpecialAccessPermissionForAssociatedPackage( - association.companionAppPackage, association.userId); + association.getPackageName(), association.getUserId()); recordAssociation(association); } @@ -582,7 +591,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind Set finalAssociations = associations; Set companionAppPackages = new HashSet<>(); for (Association association : finalAssociations) { - companionAppPackages.add(association.companionAppPackage); + companionAppPackages.add(association.getPackageName()); } file.write((out) -> { @@ -595,8 +604,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind CollectionUtils.forEach(finalAssociations, association -> { xml.startTag(null, XML_TAG_ASSOCIATION) - .attribute(null, XML_ATTR_PACKAGE, association.companionAppPackage) - .attribute(null, XML_ATTR_DEVICE, association.deviceAddress) + .attribute(null, XML_ATTR_PACKAGE, association.getPackageName()) + .attribute(null, XML_ATTR_DEVICE, association.getDeviceMacAddress()) .endTag(null, XML_TAG_ASSOCIATION); }); @@ -678,7 +687,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind CollectionUtils.forEach( readAllAssociations(getNextArgInt()), a -> getOutPrintWriter() - .println(a.companionAppPackage + " " + a.deviceAddress)); + .println(a.getPackageName() + " " + a.getDeviceMacAddress())); } break; case "associate": {