Merge "Add new @SystemApi for specifying AddressType and IRK" am: bf516b9e11
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1641559 Change-Id: I616502ee58d95cbc20fd38b395f7f0e294b5713e
This commit is contained in:
@@ -8689,6 +8689,8 @@ package android.bluetooth {
|
|||||||
field public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
|
field public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
|
||||||
field public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
|
field public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
|
||||||
field public static final String ACTION_UUID = "android.bluetooth.device.action.UUID";
|
field public static final String ACTION_UUID = "android.bluetooth.device.action.UUID";
|
||||||
|
field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
|
||||||
|
field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
|
||||||
field public static final int BOND_BONDED = 12; // 0xc
|
field public static final int BOND_BONDED = 12; // 0xc
|
||||||
field public static final int BOND_BONDING = 11; // 0xb
|
field public static final int BOND_BONDING = 11; // 0xb
|
||||||
field public static final int BOND_NONE = 10; // 0xa
|
field public static final int BOND_NONE = 10; // 0xa
|
||||||
|
|||||||
@@ -1728,6 +1728,17 @@ package android.bluetooth.le {
|
|||||||
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR;
|
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class ScanFilter implements android.os.Parcelable {
|
||||||
|
method public int getAddressType();
|
||||||
|
method @Nullable public byte[] getIrk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ScanFilter.Builder {
|
||||||
|
method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int);
|
||||||
|
method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int, @NonNull byte[]);
|
||||||
|
field public static final int LEN_IRK_OCTETS = 16; // 0x10
|
||||||
|
}
|
||||||
|
|
||||||
public final class ScanSettings implements android.os.Parcelable {
|
public final class ScanSettings implements android.os.Parcelable {
|
||||||
field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3
|
field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3
|
||||||
field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
|
field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ import android.os.SystemProperties;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -3118,6 +3120,25 @@ public final class BluetoothAdapter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether a String Bluetooth address, such as "00:43:A8:23:10:F0"
|
||||||
|
* is a RANDOM STATIC address.
|
||||||
|
*
|
||||||
|
* RANDOM STATIC: (addr & 0b11) == 0b11
|
||||||
|
* RANDOM RESOLVABLE: (addr & 0b11) == 0b10
|
||||||
|
* RANDOM non-RESOLVABLE: (addr & 0b11) == 0b00
|
||||||
|
*
|
||||||
|
* @param address Bluetooth address as string
|
||||||
|
* @return true if the 2 Least Significant Bits of the address equals 0b11.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static boolean isAddressRandomStatic(@NonNull String address) {
|
||||||
|
Preconditions.checkNotNull(address);
|
||||||
|
return checkBluetoothAddress(address)
|
||||||
|
&& (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11;
|
||||||
|
}
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
/*package*/ IBluetoothManager getBluetoothManager() {
|
/*package*/ IBluetoothManager getBluetoothManager() {
|
||||||
return mManagerService;
|
return mManagerService;
|
||||||
|
|||||||
@@ -1002,6 +1002,24 @@ public final class BluetoothDevice implements Parcelable {
|
|||||||
public static final String EXTRA_MAS_INSTANCE =
|
public static final String EXTRA_MAS_INSTANCE =
|
||||||
"android.bluetooth.device.extra.MAS_INSTANCE";
|
"android.bluetooth.device.extra.MAS_INSTANCE";
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(
|
||||||
|
prefix = { "ADDRESS_TYPE_" },
|
||||||
|
value = {
|
||||||
|
/** Hardware MAC Address */
|
||||||
|
ADDRESS_TYPE_PUBLIC,
|
||||||
|
/** Address is either resolvable, non-resolvable or static.*/
|
||||||
|
ADDRESS_TYPE_RANDOM,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public @interface AddressType {}
|
||||||
|
|
||||||
|
/** Hardware MAC Address of the device */
|
||||||
|
public static final int ADDRESS_TYPE_PUBLIC = 0;
|
||||||
|
/** Address is either resolvable, non-resolvable or static. */
|
||||||
|
public static final int ADDRESS_TYPE_RANDOM = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazy initialization. Guaranteed final after first object constructed, or
|
* Lazy initialization. Guaranteed final after first object constructed, or
|
||||||
* getService() called.
|
* getService() called.
|
||||||
@@ -1010,6 +1028,7 @@ public final class BluetoothDevice implements Parcelable {
|
|||||||
private static volatile IBluetooth sService;
|
private static volatile IBluetooth sService;
|
||||||
|
|
||||||
private final String mAddress;
|
private final String mAddress;
|
||||||
|
@AddressType private final int mAddressType;
|
||||||
|
|
||||||
/*package*/
|
/*package*/
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
@@ -1064,6 +1083,7 @@ public final class BluetoothDevice implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mAddress = address;
|
mAddress = address;
|
||||||
|
mAddressType = ADDRESS_TYPE_PUBLIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,15 +16,19 @@
|
|||||||
|
|
||||||
package android.bluetooth.le;
|
package android.bluetooth.le;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothDevice.AddressType;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.android.internal.util.BitUtils;
|
import com.android.internal.util.BitUtils;
|
||||||
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -53,6 +57,11 @@ public final class ScanFilter implements Parcelable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final String mDeviceAddress;
|
private final String mDeviceAddress;
|
||||||
|
|
||||||
|
private final @AddressType int mAddressType;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final byte[] mIrk;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final ParcelUuid mServiceUuid;
|
private final ParcelUuid mServiceUuid;
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -79,12 +88,12 @@ public final class ScanFilter implements Parcelable {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public static final ScanFilter EMPTY = new ScanFilter.Builder().build();
|
public static final ScanFilter EMPTY = new ScanFilter.Builder().build();
|
||||||
|
|
||||||
|
|
||||||
private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
|
private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
|
||||||
ParcelUuid uuidMask, ParcelUuid solicitationUuid,
|
ParcelUuid uuidMask, ParcelUuid solicitationUuid,
|
||||||
ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
|
ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
|
||||||
byte[] serviceData, byte[] serviceDataMask,
|
byte[] serviceData, byte[] serviceDataMask,
|
||||||
int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) {
|
int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask,
|
||||||
|
@AddressType int addressType, @Nullable byte[] irk) {
|
||||||
mDeviceName = name;
|
mDeviceName = name;
|
||||||
mServiceUuid = uuid;
|
mServiceUuid = uuid;
|
||||||
mServiceUuidMask = uuidMask;
|
mServiceUuidMask = uuidMask;
|
||||||
@@ -97,6 +106,8 @@ public final class ScanFilter implements Parcelable {
|
|||||||
mManufacturerId = manufacturerId;
|
mManufacturerId = manufacturerId;
|
||||||
mManufacturerData = manufacturerData;
|
mManufacturerData = manufacturerData;
|
||||||
mManufacturerDataMask = manufacturerDataMask;
|
mManufacturerDataMask = manufacturerDataMask;
|
||||||
|
mAddressType = addressType;
|
||||||
|
mIrk = irk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -280,6 +291,23 @@ public final class ScanFilter implements Parcelable {
|
|||||||
return mDeviceAddress;
|
return mDeviceAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public @AddressType int getAddressType() {
|
||||||
|
return mAddressType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@Nullable
|
||||||
|
public byte[] getIrk() {
|
||||||
|
return mIrk;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public byte[] getServiceData() {
|
public byte[] getServiceData() {
|
||||||
return mServiceData;
|
return mServiceData;
|
||||||
@@ -516,8 +544,16 @@ public final class ScanFilter implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
public static final int LEN_IRK_OCTETS = 16;
|
||||||
|
|
||||||
private String mDeviceName;
|
private String mDeviceName;
|
||||||
private String mDeviceAddress;
|
private String mDeviceAddress;
|
||||||
|
private @AddressType int mAddressType = BluetoothDevice.ADDRESS_TYPE_PUBLIC;
|
||||||
|
private byte[] mIrk;
|
||||||
|
|
||||||
private ParcelUuid mServiceUuid;
|
private ParcelUuid mServiceUuid;
|
||||||
private ParcelUuid mUuidMask;
|
private ParcelUuid mUuidMask;
|
||||||
@@ -546,14 +582,130 @@ public final class ScanFilter implements Parcelable {
|
|||||||
*
|
*
|
||||||
* @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
|
* @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
|
||||||
* format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
|
* format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
|
||||||
* BluetoothAdapter#checkBluetoothAddress}.
|
* BluetoothAdapter#checkBluetoothAddress}. The @AddressType is defaulted to {@link
|
||||||
|
* BluetoothDevice#ADDRESS_TYPE_PUBLIC}
|
||||||
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
|
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
|
||||||
*/
|
*/
|
||||||
public Builder setDeviceAddress(String deviceAddress) {
|
public Builder setDeviceAddress(String deviceAddress) {
|
||||||
if (deviceAddress != null && !BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
|
return setDeviceAddress(mDeviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set filter on Address with AddressType
|
||||||
|
*
|
||||||
|
* <p>This key is used to resolve a private address from a public address.
|
||||||
|
*
|
||||||
|
* @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
|
||||||
|
* format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
|
||||||
|
* BluetoothAdapter#checkBluetoothAddress}. May be any type of address.
|
||||||
|
* @param addressType indication of the type of address
|
||||||
|
* e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
|
||||||
|
* or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM}
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
|
||||||
|
* @throws IllegalArgumentException If the {@code addressType} is invalid length
|
||||||
|
* @throws NullPointerException if {@code deviceAddress} is null.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@SystemApi
|
||||||
|
public Builder setDeviceAddress(@NonNull String deviceAddress,
|
||||||
|
@AddressType int addressType) {
|
||||||
|
return setDeviceAddressInternal(deviceAddress, addressType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set filter on Address with AddressType and the Identity Resolving Key (IRK).
|
||||||
|
*
|
||||||
|
* <p>The IRK is used to resolve a {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} from
|
||||||
|
* a PRIVATE_ADDRESS type.
|
||||||
|
*
|
||||||
|
* @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
|
||||||
|
* format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
|
||||||
|
* BluetoothAdapter#checkBluetoothAddress}. This Address type must only be PUBLIC OR RANDOM
|
||||||
|
* STATIC.
|
||||||
|
* @param addressType indication of the type of address
|
||||||
|
* e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
|
||||||
|
* or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM}
|
||||||
|
* @param irk non-null byte array representing the Identity Resolving Key
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
|
||||||
|
* @throws IllegalArgumentException if the {@code irk} is invalid length.
|
||||||
|
* @throws IllegalArgumentException If the {@code addressType} is invalid length or is not
|
||||||
|
* PUBLIC or RANDOM STATIC when an IRK is present.
|
||||||
|
* @throws NullPointerException if {@code deviceAddress} or {@code irk} is null.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@SystemApi
|
||||||
|
public Builder setDeviceAddress(@NonNull String deviceAddress,
|
||||||
|
@AddressType int addressType,
|
||||||
|
@NonNull byte[] irk) {
|
||||||
|
Preconditions.checkNotNull(irk);
|
||||||
|
if (irk.length != LEN_IRK_OCTETS) {
|
||||||
|
throw new IllegalArgumentException("'irk' is invalid length!");
|
||||||
|
}
|
||||||
|
return setDeviceAddressInternal(deviceAddress, addressType, irk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set filter on Address with AddressType and the Identity Resolving Key (IRK).
|
||||||
|
*
|
||||||
|
* <p>Internal setter for the device address
|
||||||
|
*
|
||||||
|
* @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
|
||||||
|
* format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
|
||||||
|
* BluetoothAdapter#checkBluetoothAddress}.
|
||||||
|
* @param addressType indication of the type of address
|
||||||
|
* e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
|
||||||
|
* @param irk non-null byte array representing the Identity Resolving Address; nullable
|
||||||
|
* internally.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
|
||||||
|
* @throws IllegalArgumentException If the {@code addressType} is invalid length.
|
||||||
|
* @throws NullPointerException if {@code deviceAddress} is null.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private Builder setDeviceAddressInternal(@NonNull String deviceAddress,
|
||||||
|
@AddressType int addressType,
|
||||||
|
@Nullable byte[] irk) {
|
||||||
|
|
||||||
|
// Make sure our deviceAddress is valid!
|
||||||
|
Preconditions.checkNotNull(deviceAddress);
|
||||||
|
if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
|
||||||
throw new IllegalArgumentException("invalid device address " + deviceAddress);
|
throw new IllegalArgumentException("invalid device address " + deviceAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify type range
|
||||||
|
if (addressType < BluetoothDevice.ADDRESS_TYPE_PUBLIC
|
||||||
|
|| addressType > BluetoothDevice.ADDRESS_TYPE_RANDOM) {
|
||||||
|
throw new IllegalArgumentException("'addressType' is invalid!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// IRK can only be used for a PUBLIC or RANDOM (STATIC) Address.
|
||||||
|
if (addressType == BluetoothDevice.ADDRESS_TYPE_RANDOM) {
|
||||||
|
// Don't want a bad combination of address and irk!
|
||||||
|
if (irk != null) {
|
||||||
|
// Since there are 3 possible RANDOM subtypes we must check to make sure
|
||||||
|
// the correct type of address is used.
|
||||||
|
if (!BluetoothAdapter.isAddressRandomStatic(deviceAddress)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid combination: IRK requires either a PUBLIC or "
|
||||||
|
+ "RANDOM (STATIC) Address");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC doesn't require extra work
|
||||||
|
// Without an IRK any address may be accepted
|
||||||
|
|
||||||
mDeviceAddress = deviceAddress;
|
mDeviceAddress = deviceAddress;
|
||||||
|
mAddressType = addressType;
|
||||||
|
mIrk = irk;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,7 +879,8 @@ public final class ScanFilter implements Parcelable {
|
|||||||
mServiceUuid, mUuidMask, mServiceSolicitationUuid,
|
mServiceUuid, mUuidMask, mServiceSolicitationUuid,
|
||||||
mServiceSolicitationUuidMask,
|
mServiceSolicitationUuidMask,
|
||||||
mServiceDataUuid, mServiceData, mServiceDataMask,
|
mServiceDataUuid, mServiceData, mServiceDataMask,
|
||||||
mManufacturerId, mManufacturerData, mManufacturerDataMask);
|
mManufacturerId, mManufacturerData, mManufacturerDataMask,
|
||||||
|
mAddressType, mIrk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user