diff options
Diffstat (limited to 'framework/java')
11 files changed, 476 insertions, 230 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 716d808a11..2b03261cd6 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -1445,25 +1445,8 @@ public final class BluetoothAdapter { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @NonNull ParcelUuid[] getUuids() { - if (getState() != STATE_ON) { - return new ParcelUuid[0]; - } - try { - mServiceLock.readLock().lock(); - if (mService != null) { - final SynchronousResultReceiver<List<ParcelUuid>> recv = - new SynchronousResultReceiver(); - mService.getUuids(mAttributionSource, recv); - List<ParcelUuid> parcels = recv.awaitResultNoInterrupt(getSyncTimeout()) - .getValue(new ArrayList<>()); - return parcels.toArray(new ParcelUuid[parcels.size()]); - } - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } finally { - mServiceLock.readLock().unlock(); - } - return new ParcelUuid[0]; + List<ParcelUuid> parcels = getUuidsList(); + return parcels.toArray(new ParcelUuid[parcels.size()]); } /** @@ -1475,7 +1458,22 @@ public final class BluetoothAdapter { @SystemApi @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @NonNull List<ParcelUuid> getUuidsList() { - return Arrays.asList(getUuids()); + List<ParcelUuid> defaultValue = new ArrayList<>(); + if (getState() != STATE_ON || mService == null) { + return defaultValue; + } + mServiceLock.readLock().lock(); + try { + final SynchronousResultReceiver<List<ParcelUuid>> recv = + new SynchronousResultReceiver(); + mService.getUuids(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } finally { + mServiceLock.readLock().unlock(); + } + return defaultValue; } /** diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index 70266741ad..ee9c691134 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; +import android.bluetooth.BluetoothGattCharacteristic.WriteType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; @@ -423,9 +424,6 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) characteristic.setValue(value); callback.onCharacteristicRead(BluetoothGatt.this, characteristic, value, status); - // Keep calling deprecated callback to maintain app compatibility - callback.onCharacteristicRead(BluetoothGatt.this, characteristic, - status); } } }); @@ -526,9 +524,6 @@ public final class BluetoothGatt implements BluetoothProfile { characteristic.setValue(value); callback.onCharacteristicChanged(BluetoothGatt.this, characteristic, value); - // Keep calling deprecated callback to maintain app compatibility - callback.onCharacteristicChanged(BluetoothGatt.this, - characteristic); } } }); @@ -585,8 +580,6 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) descriptor.setValue(value); callback.onDescriptorRead(BluetoothGatt.this, descriptor, status, value); - // Keep calling deprecated callback to maintain app compatibility - callback.onDescriptorRead(BluetoothGatt.this, descriptor, status); } } }); @@ -1305,7 +1298,6 @@ public final class BluetoothGatt implements BluetoothProfile { return true; } - /** * Writes a given characteristic and its values to the associated remote device. * @@ -1318,7 +1310,8 @@ public final class BluetoothGatt implements BluetoothProfile { * @throws IllegalArgumentException if characteristic or its value are null * * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], - * int)} as this is not memory safe. + * int)} as this is not memory safe because it relies on a {@link BluetoothGattCharacteristic} + * object whose underlying fields are subject to change outside this method. */ @Deprecated @RequiresLegacyBluetoothPermission @@ -1338,7 +1331,6 @@ public final class BluetoothGatt implements BluetoothProfile { @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION, - BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION, BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED, @@ -1362,7 +1354,7 @@ public final class BluetoothGatt implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @WriteOperationReturnValues public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic, - @NonNull byte[] value, int writeType) { + @NonNull byte[] value, @WriteType int writeType) { if (characteristic == null) { throw new IllegalArgumentException("characteristic must not be null"); } @@ -1487,7 +1479,8 @@ public final class BluetoothGatt implements BluetoothProfile { * @throws IllegalArgumentException if descriptor or its value are null * * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as - * this is not memory safe. + * this is not memory safe because it relies on a {@link BluetoothGattDescriptor} object + * whose underlying fields are subject to change outside this method. */ @Deprecated @RequiresLegacyBluetoothPermission diff --git a/framework/java/android/bluetooth/BluetoothGattCallback.java b/framework/java/android/bluetooth/BluetoothGattCallback.java index d0a5a1e729..3852d508c0 100644 --- a/framework/java/android/bluetooth/BluetoothGattCallback.java +++ b/framework/java/android/bluetooth/BluetoothGattCallback.java @@ -105,6 +105,7 @@ public abstract class BluetoothGattCallback { */ public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) { + onCharacteristicRead(gatt, characteristic, status); } /** @@ -155,6 +156,7 @@ public abstract class BluetoothGattCallback { */ public void onCharacteristicChanged(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) { + onCharacteristicChanged(gatt, characteristic); } /** @@ -184,6 +186,7 @@ public abstract class BluetoothGattCallback { */ public void onDescriptorRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) { + onDescriptorRead(gatt, descriptor, status); } /** diff --git a/framework/java/android/bluetooth/BluetoothGattCharacteristic.java b/framework/java/android/bluetooth/BluetoothGattCharacteristic.java index c5e986e895..92bbfcefaf 100644 --- a/framework/java/android/bluetooth/BluetoothGattCharacteristic.java +++ b/framework/java/android/bluetooth/BluetoothGattCharacteristic.java @@ -15,11 +15,14 @@ */ package android.bluetooth; +import android.annotation.IntDef; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -115,8 +118,17 @@ public class BluetoothGattCharacteristic implements Parcelable { */ public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "WRITE_TYPE_", value = { + WRITE_TYPE_DEFAULT, + WRITE_TYPE_NO_RESPONSE, + WRITE_TYPE_SIGNED + }) + public @interface WriteType{} + /** - * Write characteristic, requesting acknoledgement by the remote device + * Write characteristic, requesting acknowledgement by the remote device */ public static final int WRITE_TYPE_DEFAULT = 0x02; diff --git a/framework/java/android/bluetooth/BluetoothGattServer.java b/framework/java/android/bluetooth/BluetoothGattServer.java index 27d78475a3..8b84505e36 100644 --- a/framework/java/android/bluetooth/BluetoothGattServer.java +++ b/framework/java/android/bluetooth/BluetoothGattServer.java @@ -751,11 +751,8 @@ public final class BluetoothGattServer implements BluetoothProfile { @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION, - BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION, BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, - BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED, - BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY, BluetoothStatusCodes.ERROR_UNKNOWN }) public @interface NotifyCharacteristicReturnValues{} diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java index 9df07724cc..015f0bd6fb 100644 --- a/framework/java/android/bluetooth/BluetoothHeadset.java +++ b/framework/java/android/bluetooth/BluetoothHeadset.java @@ -49,6 +49,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeoutException; /** @@ -930,7 +931,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * * @param device is the Bluetooth device for which the audio state is being queried * @return the audio state of the device or an error code - * @throws IllegalArgumentException if the device is null + * @throws NullPointerException if the device is null * * @hide */ @@ -942,9 +943,7 @@ public final class BluetoothHeadset implements BluetoothProfile { }) public @GetAudioStateReturnValues int getAudioState(@NonNull BluetoothDevice device) { if (VDBG) log("getAudioState"); - if (device == null) { - throw new IllegalArgumentException("device cannot be null"); - } + Objects.requireNonNull(device); final IBluetoothHeadset service = mService; final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED; if (service == null) { diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index 91b7d499bb..6d416434b2 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -19,7 +19,6 @@ package android.bluetooth; import static android.bluetooth.BluetoothUtils.getSyncTimeout; -import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; @@ -78,6 +77,14 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { */ @SystemApi public interface Callback { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + GROUP_STATUS_ACTIVE, + GROUP_STATUS_INACTIVE, + }) + @interface GroupStatus {} + /** * Callback invoked when callback is registered and when codec config * changes on the remote device. @@ -89,6 +96,40 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @SystemApi void onCodecConfigChanged(int groupId, @NonNull BluetoothLeAudioCodecStatus status); + + /** + * Callback invoked when a device has been added to the group. + * It usually happens after connection or on bluetooth startup if + * the device is bonded. + * + * @param device the device which is added to the group + * @param groupId the group id + * @hide + */ + @SystemApi + void onGroupNodeAdded(@NonNull BluetoothDevice device, int groupId); + + /** + * Callback invoked when a device has been removed from the group. + * It usually happens when device gets unbonded. + * + * @param device the device which is removed from the group + * @param groupId the group id + * + * @hide + */ + @SystemApi + void onGroupNodeRemoved(@NonNull BluetoothDevice device, int groupId); + + /** + * Callback invoked the group's active state changes. + * + * @param groupId the group id + * @param groupStatus active or inactive state. + * @hide + */ + @SystemApi + void onGroupStatusChanged(int groupId, @GroupStatus int groupStatus); } @SuppressLint("AndroidFrameworkBluetoothPermission") @@ -103,6 +144,38 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { executor.execute(() -> callback.onCodecConfigChanged(groupId, status)); } } + + @Override + public void onGroupNodeAdded(@NonNull BluetoothDevice device, int groupId) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothLeAudio.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothLeAudio.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onGroupNodeAdded(device, groupId)); + } + } + + @Override + public void onGroupNodeRemoved(@NonNull BluetoothDevice device, int groupId) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothLeAudio.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothLeAudio.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onGroupNodeRemoved(device, groupId)); + } + } + + @Override + public void onGroupStatusChanged(int groupId, int groupStatus) { + for (Map.Entry<BluetoothLeAudio.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothLeAudio.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onGroupStatusChanged(groupId, groupStatus)); + } + } }; /** @@ -151,70 +224,6 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED"; /** - * Intent used to broadcast group node status information. - * - * <p>This intent will have 3 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can - * be null if no device is active. </li> - * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li> - * <li> {@link #EXTRA_LE_AUDIO_GROUP_NODE_STATUS} - Group node status. </li> - * </ul> - * - * @hide - */ - @SystemApi - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED = - "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED"; - - /** - * Intent used to broadcast group status information. - * - * <p>This intent will have 3 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can - * be null if no device is active. </li> - * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li> - * <li> {@link #EXTRA_LE_AUDIO_GROUP_STATUS} - Group status. </li> - * </ul> - * - * @hide - */ - @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_LE_AUDIO_GROUP_STATUS_CHANGED = - "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED"; - - /** - * Intent used to broadcast group audio configuration changed information. - * - * <p>This intent will have 5 extra: - * <ul> - * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li> - * <li> {@link #EXTRA_LE_AUDIO_DIRECTION} - Direction as bit mask. </li> - * <li> {@link #EXTRA_LE_AUDIO_SINK_LOCATION} - Sink location as per Bluetooth Assigned - * Numbers </li> - * <li> {@link #EXTRA_LE_AUDIO_SOURCE_LOCATION} - Source location as per Bluetooth Assigned - * Numbers </li> - * <li> {@link #EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS} - Available contexts for group as per - * Bluetooth Assigned Numbers </li> - * </ul> - * - * @hide - */ - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_LE_AUDIO_CONF_CHANGED = - "android.bluetooth.action.LE_AUDIO_CONF_CHANGED"; - - - /** * Indicates unspecified audio content. * @hide */ @@ -573,35 +582,6 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { "android.bluetooth.extra.LE_AUDIO_GROUP_ID"; /** - * Contains group node status, can be any of - * <p> - * <ul> - * <li> {@link #GROUP_NODE_ADDED} </li> - * <li> {@link #GROUP_NODE_REMOVED} </li> - * </ul> - * <p> - * @hide - */ - @SystemApi - public static final String EXTRA_LE_AUDIO_GROUP_NODE_STATUS = - "android.bluetooth.extra.LE_AUDIO_GROUP_NODE_STATUS"; - - /** - * Contains group status, can be any of - * - * <p> - * <ul> - * <li> {@link #GROUP_STATUS_ACTIVE} </li> - * <li> {@link #GROUP_STATUS_INACTIVE} </li> - * </ul> - * <p> - * @hide - */ - @SystemApi - public static final String EXTRA_LE_AUDIO_GROUP_STATUS = - "android.bluetooth.extra.LE_AUDIO_GROUP_STATUS"; - - /** * Contains bit mask for direction, bit 0 set when Sink, bit 1 set when Source. * @hide */ @@ -643,20 +623,6 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { */ public static final int GROUP_STATUS_INACTIVE = IBluetoothLeAudio.GROUP_STATUS_INACTIVE; - /** - * Indicating that node has been added to the group. - * @hide - */ - @SystemApi - public static final int GROUP_NODE_ADDED = IBluetoothLeAudio.GROUP_NODE_ADDED; - - /** - * Indicating that node has been removed from the group. - * @hide - */ - @SystemApi - public static final int GROUP_NODE_REMOVED = IBluetoothLeAudio.GROUP_NODE_REMOVED; - private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector = new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio", IBluetoothLeAudio.class.getName()) { @@ -979,6 +945,13 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { synchronized (mCallbackExecutorMap) { // If the callback map is empty, we register the service-to-app callback if (mCallbackExecutorMap.isEmpty()) { + if (!mAdapter.isEnabled()) { + /* If Bluetooth is off, just store callback and it will be registered + * when Bluetooth is on + */ + mCallbackExecutorMap.put(callback, executor); + return; + } try { final IBluetoothLeAudio service = getService(); if (service != null) { diff --git a/framework/java/android/bluetooth/BluetoothStatusCodes.java b/framework/java/android/bluetooth/BluetoothStatusCodes.java index 49b0578f8c..c81c6830eb 100644 --- a/framework/java/android/bluetooth/BluetoothStatusCodes.java +++ b/framework/java/android/bluetooth/BluetoothStatusCodes.java @@ -58,14 +58,6 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the - * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission. - * - * @hide - */ - public static final int ERROR_MISSING_BLUETOOTH_ADVERTISE_PERMISSION = 5; - - /** - * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. */ public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; @@ -79,12 +71,6 @@ public final class BluetoothStatusCodes { public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7; /** - * Error code indicating that the caller does not have the - * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission. - */ - public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; - - /** * Error code indicating that the profile service is not bound. You can bind a profile service * by calling {@link BluetoothAdapter#getProfileProxy}. */ diff --git a/framework/java/android/bluetooth/BluetoothUuid.java b/framework/java/android/bluetooth/BluetoothUuid.java index c77b981d35..8de213fcda 100644 --- a/framework/java/android/bluetooth/BluetoothUuid.java +++ b/framework/java/android/bluetooth/BluetoothUuid.java @@ -30,7 +30,9 @@ import java.util.HashSet; import java.util.UUID; /** - * Static helper methods and constants to decode the ParcelUuid of remote devices. + * Static helper methods and constants to decode the ParcelUuid of remote devices. Bluetooth service + * UUIDs are defined in the SDP section of the Bluetooth Assigned Numbers document. The constant + * 128 bit values in this class are calculated as: uuid * 2^96 + {@link #BASE_UUID}. * * @hide */ @@ -38,164 +40,321 @@ import java.util.UUID; @SuppressLint("AndroidFrameworkBluetoothPermission") public final class BluetoothUuid { - /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs - * for the various services. + /** + * UUID corresponding to the Audio sink role (also referred to as the A2DP sink role). * - * The following 128 bit values are calculated as: - * uuid * 2^96 + BASE_UUID + * @hide */ - - /** @hide */ @NonNull @SystemApi public static final ParcelUuid A2DP_SINK = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); - /** @hide */ + /** + * UUID corresponding to the Audio source role (also referred to as the A2DP source role). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid A2DP_SOURCE = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Advanced Audio Distribution Profile (A2DP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid ADV_AUDIO_DIST = ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Headset Profile (HSP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HSP = ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Headset Profile (HSP) Audio Gateway role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HSP_AG = ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Hands-Free Profile (HFP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HFP = ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Hands-Free Profile (HFP) Audio Gateway role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HFP_AG = ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Audio Video Remote Control Profile (AVRCP). + * + * @hide + */ @NonNull @SystemApi - public static final ParcelUuid AVRCP_CONTROLLER = + public static final ParcelUuid AVRCP = ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Audio Video Remote Control Profile (AVRCP) controller role. + * + * @hide + */ + @NonNull + @SystemApi + public static final ParcelUuid AVRCP_CONTROLLER = + ParcelUuid.fromString("0000110F-0000-1000-8000-00805F9B34FB"); + + /** + * UUID corresponding to the Audio Video Remote Control Profile (AVRCP) target role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid AVRCP_TARGET = ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the OBject EXchange (OBEX) Object Push Profile (OPP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid OBEX_OBJECT_PUSH = ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb"); - /** @hide */ + + /** + * UUID corresponding to the Human Interface Device (HID) profile. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HID = ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb"); - /** @hide */ + + /** + * UUID corresponding to the Human Interface Device over GATT Profile (HOGP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HOGP = ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb"); - /** @hide */ + + /** + * UUID corresponding to the Personal Area Network User (PANU) role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid PANU = ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Network Access Point (NAP) role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid NAP = ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Bluetooth Network Encapsulation Protocol (BNEP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid BNEP = ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Phonebook Access Profile (PBAP) client role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid PBAP_PCE = ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Phonebook Access Profile (PBAP) server role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid PBAP_PSE = ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Message Access Profile (MAP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid MAP = ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Message Notification Server (MNS) role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid MNS = ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Message Access Server (MAS) role. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid MAS = ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Sim Access Profile (SAP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid SAP = ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Hearing Aid Profile. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HEARING_AID = ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb"); - /** @hide */ + + /** + * UUID corresponding to the Hearing Access Service (HAS). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid HAS = ParcelUuid.fromString("00001854-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to Audio Stream Control (also known as Bluetooth Low Energy Audio). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid LE_AUDIO = ParcelUuid.fromString("0000184E-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Device Identification Profile (DIP). + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid DIP = ParcelUuid.fromString("00001200-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Volume Control Service. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid VOLUME_CONTROL = ParcelUuid.fromString("00001844-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Generic Media Control Service. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid GENERIC_MEDIA_CONTROL = ParcelUuid.fromString("00001849-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Media Control Service. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid MEDIA_CONTROL = ParcelUuid.fromString("00001848-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Coordinated Set Identification Service. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid COORDINATED_SET = ParcelUuid.fromString("00001846-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Common Audio Service. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid CAP = ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * UUID corresponding to the Broadcast Audio Scan Service (also known as LE Audio Broadcast + * Assistant). + * + * @hide + */ @NonNull public static final ParcelUuid BATTERY = ParcelUuid.fromString("0000180F-0000-1000-8000-00805F9B34FB"); @@ -204,7 +363,12 @@ public final class BluetoothUuid { @SystemApi public static final ParcelUuid BASS = ParcelUuid.fromString("0000184F-0000-1000-8000-00805F9B34FB"); - /** @hide */ + + /** + * Base UUID to calculate all other UUIDs defined in this class. + * + * @hide + */ @NonNull @SystemApi public static final ParcelUuid BASE_UUID = diff --git a/framework/java/android/bluetooth/le/ScanFilter.java b/framework/java/android/bluetooth/le/ScanFilter.java index cb0711f1d1..3edde10f96 100644 --- a/framework/java/android/bluetooth/le/ScanFilter.java +++ b/framework/java/android/bluetooth/le/ScanFilter.java @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice.AddressType; +import android.bluetooth.le.ScanRecord.AdvertisingDataType; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; @@ -43,6 +44,7 @@ import java.util.UUID; * <li>Mac address of the remote device. * <li>Service data which is the data associated with a service. * <li>Manufacturer specific data which is the data associated with a particular manufacturer. + * <li>Advertising data type and corresponding data. * * @see ScanResult * @see BluetoothLeScanner @@ -83,7 +85,7 @@ public final class ScanFilter implements Parcelable { @Nullable private final byte[] mManufacturerDataMask; - private int mAdvertisingDataType = -1; + private int mAdvertisingDataType = ScanRecord.DATA_TYPE_NONE; @Nullable private final byte[] mAdvertisingData; @Nullable @@ -303,7 +305,7 @@ public final class ScanFilter implements Parcelable { advertisingDataMask = new byte[advertisingDataMaskLength]; in.readByteArray(advertisingDataMask); } - builder.setAdvertisingDataWithType(advertisingDataType, advertisingData, + builder.setAdvertisingDataTypeWithData(advertisingDataType, advertisingData, advertisingDataMask); } @@ -403,16 +405,26 @@ public final class ScanFilter implements Parcelable { } /** - * Returns the advertising data type. -1 if the type is not set. - */ + * Returns the advertising data type of this filter. + * Returns {@link ScanRecord#DATA_TYPE_NONE} if the type is not set. + * The values of advertising data type are defined in the Bluetooth Generic Access Profile + * (https://www.bluetooth.com/specifications/assigned-numbers/) + */ + @AdvertisingDataType public int getAdvertisingDataType() { return mAdvertisingDataType; } + /** + * Returns the advertising data of this filter. + */ public @Nullable byte[] getAdvertisingData() { return mAdvertisingData; } + /** + * Returns the advertising data mask of this filter. + */ public @Nullable byte[] getAdvertisingDataMask() { return mAdvertisingDataMask; } @@ -477,7 +489,7 @@ public final class ScanFilter implements Parcelable { } // Advertising data type match - if (mAdvertisingDataType >= 0) { + if (mAdvertisingDataType > 0) { byte[] advertisingData = scanRecord.getAdvertisingDataMap().get(mAdvertisingDataType); if (advertisingData == null || !matchesPartialData(mAdvertisingData, mAdvertisingDataMask, advertisingData)) { @@ -665,7 +677,7 @@ public final class ScanFilter implements Parcelable { private byte[] mManufacturerData; private byte[] mManufacturerDataMask; - private int mAdvertisingDataType = -1; + private int mAdvertisingDataType = ScanRecord.DATA_TYPE_NONE; private byte[] mAdvertisingData; private byte[] mAdvertisingDataMask; @@ -978,15 +990,19 @@ public final class ScanFilter implements Parcelable { * For any bit in the mask, set it the 1 if it needs to match the one in * advertising data, otherwise set it to 0. * <p> + * The values of {@code advertisingDataType} are assigned by Bluetooth SIG. For more + * details refer to Bluetooth Generic Access Profile. + * (https://www.bluetooth.com/specifications/assigned-numbers/) * The {@code advertisingDataMask} must have the same length of {@code advertisingData}. * * @throws IllegalArgumentException If the {@code advertisingDataType} is invalid, {@code - * advertisingData} is null while {@code advertisingDataMask} is not, or {@code + * advertisingData} or {@code advertisingDataMask} is null or {@code * advertisingData} and {@code advertisingDataMask} have different length. */ - public @NonNull Builder setAdvertisingDataWithType(int advertisingDataType, - @Nullable byte[] advertisingData, @Nullable byte[] advertisingDataMask) { - if (advertisingDataType < -1) { + public @NonNull Builder setAdvertisingDataTypeWithData( + @AdvertisingDataType int advertisingDataType, @NonNull byte[] advertisingData, + @NonNull byte[] advertisingDataMask) { + if (advertisingDataType < 0) { throw new IllegalArgumentException("invalid advertising data type"); } if (mAdvertisingDataMask != null) { @@ -1007,6 +1023,24 @@ public final class ScanFilter implements Parcelable { return this; } + + /** + * Set filter on advertising data with specific advertising data type. + * <p> + * The values of {@code advertisingDataType} are assigned by Bluetooth SIG. For more + * details refer to Bluetooth Generic Access Profile. + * (https://www.bluetooth.com/specifications/assigned-numbers/) + * @throws IllegalArgumentException If the {@code advertisingDataType} is invalid + */ + public @NonNull Builder setAdvertisingDataType( + @AdvertisingDataType int advertisingDataType) { + if (advertisingDataType < 0) { + throw new IllegalArgumentException("invalid advertising data type"); + } + mAdvertisingDataType = advertisingDataType; + return this; + } + /** * Build {@link ScanFilter}. * diff --git a/framework/java/android/bluetooth/le/ScanRecord.java b/framework/java/android/bluetooth/le/ScanRecord.java index d96f396d03..2ede597ed4 100644 --- a/framework/java/android/bluetooth/le/ScanRecord.java +++ b/framework/java/android/bluetooth/le/ScanRecord.java @@ -16,6 +16,7 @@ package android.bluetooth.le; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -26,6 +27,8 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -41,25 +44,107 @@ public final class ScanRecord { private static final String TAG = "ScanRecord"; + /** @hide */ + @IntDef(prefix = "DATA_TYPE_", value = { + DATA_TYPE_FLAGS, + DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL, + DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE, + DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL, + DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE, + DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL, + DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE, + DATA_TYPE_LOCAL_NAME_SHORT, + DATA_TYPE_LOCAL_NAME_COMPLETE, + DATA_TYPE_TX_POWER_LEVEL, + DATA_TYPE_CLASS_OF_DEVICE, + DATA_TYPE_SIMPLE_PAIRING_HASH_C, + DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R, + DATA_TYPE_DEVICE_ID, + DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS, + DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE, + DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT, + DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT, + DATA_TYPE_SERVICE_DATA_16_BIT, + DATA_TYPE_PUBLIC_TARGET_ADDRESS, + DATA_TYPE_RANDOM_TARGET_ADDRESS, + DATA_TYPE_APPEARANCE, + DATA_TYPE_ADVERTISING_INTERVAL, + DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS, + DATA_TYPE_LE_ROLE, + DATA_TYPE_SIMPLE_PAIRING_HASH_C_256, + DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256, + DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT, + DATA_TYPE_SERVICE_DATA_32_BIT, + DATA_TYPE_SERVICE_DATA_128_BIT, + DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE, + DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE, + DATA_TYPE_URI, + DATA_TYPE_INDOOR_POSITIONING, + DATA_TYPE_TRANSPORT_DISCOVERY_DATA, + DATA_TYPE_LE_SUPPORTED_FEATURES, + DATA_TYPE_CHANNEL_MAP_UPDATE_INDICATION, + DATA_TYPE_PB_ADV, + DATA_TYPE_MESH_MESSAGE, + DATA_TYPE_MESH_BEACON, + DATA_TYPE_BIG_INFO, + DATA_TYPE_BROADCAST_CODE, + DATA_TYPE_RESOLVABLE_SET_IDENTIFIER, + DATA_TYPE_ADVERTISING_INTERVAL_LONG, + DATA_TYPE_3D_INFORMATION_DATA, + DATA_TYPE_MANUFACTURER_SPECIFIC_DATA, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AdvertisingDataType {} + // The following data type values are assigned by Bluetooth SIG. - // For more details refer to Bluetooth 4.1 specification, Volume 3, Part C, Section 18. - private static final int DATA_TYPE_FLAGS = 0x01; - private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02; - private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03; - private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04; - private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05; - private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06; - private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07; - private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08; - private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09; - private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A; - private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16; - private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20; - private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21; - private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14; - private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F; - private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15; - private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; + // For more details refer to Bluetooth Generic Access Profile. + public static final int DATA_TYPE_NONE = -1; + public static final int DATA_TYPE_FLAGS = 0x01; + public static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02; + public static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03; + public static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04; + public static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05; + public static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06; + public static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07; + public static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08; + public static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09; + public static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A; + public static final int DATA_TYPE_CLASS_OF_DEVICE = 0x0D; + public static final int DATA_TYPE_SIMPLE_PAIRING_HASH_C = 0x0E; + public static final int DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F; + public static final int DATA_TYPE_DEVICE_ID = 0x10; + public static final int DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11; + public static final int DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE = 0x12; + public static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14; + public static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15; + public static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16; + public static final int DATA_TYPE_PUBLIC_TARGET_ADDRESS = 0x17; + public static final int DATA_TYPE_RANDOM_TARGET_ADDRESS = 0x18; + public static final int DATA_TYPE_APPEARANCE = 0x19; + public static final int DATA_TYPE_ADVERTISING_INTERVAL = 0x1A; + public static final int DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B; + public static final int DATA_TYPE_LE_ROLE = 0x1C; + public static final int DATA_TYPE_SIMPLE_PAIRING_HASH_C_256 = 0x1D; + public static final int DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E; + public static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F; + public static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20; + public static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21; + public static final int DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22; + public static final int DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23; + public static final int DATA_TYPE_URI = 0x24; + public static final int DATA_TYPE_INDOOR_POSITIONING = 0x25; + public static final int DATA_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26; + public static final int DATA_TYPE_LE_SUPPORTED_FEATURES = 0x27; + public static final int DATA_TYPE_CHANNEL_MAP_UPDATE_INDICATION = 0x28; + public static final int DATA_TYPE_PB_ADV = 0x29; + public static final int DATA_TYPE_MESH_MESSAGE = 0x2A; + public static final int DATA_TYPE_MESH_BEACON = 0x2B; + public static final int DATA_TYPE_BIG_INFO = 0x2C; + public static final int DATA_TYPE_BROADCAST_CODE = 0x2D; + public static final int DATA_TYPE_RESOLVABLE_SET_IDENTIFIER = 0x2E; + public static final int DATA_TYPE_ADVERTISING_INTERVAL_LONG = 0x2F; + public static final int DATA_TYPE_3D_INFORMATION_DATA = 0x3D; + public static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; // Flags of the advertising data. private final int mAdvertiseFlags; @@ -170,6 +255,8 @@ public final class ScanRecord { /** * Returns a map of advertising data type and its corresponding advertising data. + * The values of advertising data type are defined in the Bluetooth Generic Access Profile + * (https://www.bluetooth.com/specifications/assigned-numbers/) */ public @NonNull Map<Integer, byte[]> getAdvertisingDataMap() { return mAdvertisingDataMap; |
