Add new @SystemApi for specifying AddressType and IRK
Bug: 178234318 Test: compiles and runs Tag: #feature Change-Id: Ib67e681af01260df98602003b2aca47963494c6f
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_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
|
||||
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_BONDING = 11; // 0xb
|
||||
field public static final int BOND_NONE = 10; // 0xa
|
||||
|
||||
@@ -1726,6 +1726,17 @@ package android.bluetooth.le {
|
||||
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 {
|
||||
field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
|
||||
field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
|
||||
|
||||
@@ -52,6 +52,8 @@ import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -3118,6 +3120,25 @@ public final class BluetoothAdapter {
|
||||
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
|
||||
/*package*/ IBluetoothManager getBluetoothManager() {
|
||||
return mManagerService;
|
||||
|
||||
@@ -1002,6 +1002,24 @@ public final class BluetoothDevice implements Parcelable {
|
||||
public static final String 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
|
||||
* getService() called.
|
||||
@@ -1010,6 +1028,7 @@ public final class BluetoothDevice implements Parcelable {
|
||||
private static volatile IBluetooth sService;
|
||||
|
||||
private final String mAddress;
|
||||
@AddressType private final int mAddressType;
|
||||
|
||||
/*package*/
|
||||
@UnsupportedAppUsage
|
||||
@@ -1064,6 +1083,7 @@ public final class BluetoothDevice implements Parcelable {
|
||||
}
|
||||
|
||||
mAddress = address;
|
||||
mAddressType = ADDRESS_TYPE_PUBLIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,15 +16,19 @@
|
||||
|
||||
package android.bluetooth.le;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothDevice.AddressType;
|
||||
import android.os.Parcel;
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.BitUtils;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -53,6 +57,11 @@ public final class ScanFilter implements Parcelable {
|
||||
@Nullable
|
||||
private final String mDeviceAddress;
|
||||
|
||||
private final @AddressType int mAddressType;
|
||||
|
||||
@Nullable
|
||||
private final byte[] mIrk;
|
||||
|
||||
@Nullable
|
||||
private final ParcelUuid mServiceUuid;
|
||||
@Nullable
|
||||
@@ -79,12 +88,12 @@ public final class ScanFilter implements Parcelable {
|
||||
/** @hide */
|
||||
public static final ScanFilter EMPTY = new ScanFilter.Builder().build();
|
||||
|
||||
|
||||
private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
|
||||
ParcelUuid uuidMask, ParcelUuid solicitationUuid,
|
||||
ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
|
||||
byte[] serviceData, byte[] serviceDataMask,
|
||||
int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) {
|
||||
int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask,
|
||||
@AddressType int addressType, @Nullable byte[] irk) {
|
||||
mDeviceName = name;
|
||||
mServiceUuid = uuid;
|
||||
mServiceUuidMask = uuidMask;
|
||||
@@ -97,6 +106,8 @@ public final class ScanFilter implements Parcelable {
|
||||
mManufacturerId = manufacturerId;
|
||||
mManufacturerData = manufacturerData;
|
||||
mManufacturerDataMask = manufacturerDataMask;
|
||||
mAddressType = addressType;
|
||||
mIrk = irk;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -280,6 +291,23 @@ public final class ScanFilter implements Parcelable {
|
||||
return mDeviceAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public @AddressType int getAddressType() {
|
||||
return mAddressType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@Nullable
|
||||
public byte[] getIrk() {
|
||||
return mIrk;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getServiceData() {
|
||||
return mServiceData;
|
||||
@@ -516,8 +544,16 @@ public final class ScanFilter implements Parcelable {
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int LEN_IRK_OCTETS = 16;
|
||||
|
||||
private String mDeviceName;
|
||||
private String mDeviceAddress;
|
||||
private @AddressType int mAddressType = BluetoothDevice.ADDRESS_TYPE_PUBLIC;
|
||||
private byte[] mIrk;
|
||||
|
||||
private ParcelUuid mServiceUuid;
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
mAddressType = addressType;
|
||||
mIrk = irk;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -727,7 +879,8 @@ public final class ScanFilter implements Parcelable {
|
||||
mServiceUuid, mUuidMask, mServiceSolicitationUuid,
|
||||
mServiceSolicitationUuidMask,
|
||||
mServiceDataUuid, mServiceData, mServiceDataMask,
|
||||
mManufacturerId, mManufacturerData, mManufacturerDataMask);
|
||||
mManufacturerId, mManufacturerData, mManufacturerDataMask,
|
||||
mAddressType, mIrk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user