diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2021-03-21 20:15:38 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-03-21 20:15:38 +0000 |
commit | bf516b9e11f407b0bb9be8dc5aa83d5ef19cff9b (patch) | |
tree | 63fbdb90e86e3e1e2e94c5b73f8a4a05c4083c19 /core/java/android | |
parent | cfa02cd6872821e695d9c11df3c28408dc84bdb9 (diff) | |
parent | 045fe260e1677f7442fbecc66085acd1dd23ff7b (diff) |
Merge "Add new @SystemApi for specifying AddressType and IRK"
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 21 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothDevice.java | 20 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/ScanFilter.java | 163 |
3 files changed, 199 insertions, 5 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index cc0b22afe38d..38863c2c8ccf 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -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; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 41bc77651db6..c30b8af3da53 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -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 diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 7511fd051e41..86721502d409 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -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); } } } |