Loading framework/java/android/bluetooth/BluetoothAdapter.java +21 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading framework/java/android/bluetooth/BluetoothDevice.java +20 −0 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading Loading @@ -1064,6 +1083,7 @@ public final class BluetoothDevice implements Parcelable { } mAddress = address; mAddressType = ADDRESS_TYPE_PUBLIC; } @Override Loading framework/java/android/bluetooth/le/ScanFilter.java +158 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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; Loading @@ -97,6 +106,8 @@ public final class ScanFilter implements Parcelable { mManufacturerId = manufacturerId; mManufacturerData = manufacturerData; mManufacturerDataMask = manufacturerDataMask; mAddressType = addressType; mIrk = irk; } @Override Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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); } } } Loading
framework/java/android/bluetooth/BluetoothAdapter.java +21 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading
framework/java/android/bluetooth/BluetoothDevice.java +20 −0 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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 Loading Loading @@ -1064,6 +1083,7 @@ public final class BluetoothDevice implements Parcelable { } mAddress = address; mAddressType = ADDRESS_TYPE_PUBLIC; } @Override Loading
framework/java/android/bluetooth/le/ScanFilter.java +158 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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; Loading @@ -97,6 +106,8 @@ public final class ScanFilter implements Parcelable { mManufacturerId = manufacturerId; mManufacturerData = manufacturerData; mManufacturerDataMask = manufacturerDataMask; mAddressType = addressType; mIrk = irk; } @Override Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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); } } }