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
This commit is contained in:
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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<Association> 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) {
|
||||
|
||||
@@ -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<String> getAssociations(String callingPackage, int userId);
|
||||
List<Association> getAssociationsForUser(int userId);
|
||||
|
||||
void disassociate(String deviceMacAddress, String callingPackage);
|
||||
|
||||
boolean hasNotificationAccess(in ComponentName component);
|
||||
|
||||
@@ -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<String> 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<Association> 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<Association> finalAssociations = associations;
|
||||
Set<String> 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": {
|
||||
|
||||
Reference in New Issue
Block a user