diff --git a/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java b/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java new file mode 100644 index 0000000000000..cb47280acc7ec --- /dev/null +++ b/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java @@ -0,0 +1,788 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * This class represents an LE Audio Broadcast Source and the associated information that is needed + * by Broadcast Audio Scan Service (BASS) residing on a Scan Delegator. + * + *
For example, the Scan Delegator on an LE Audio Broadcast Sink can use the information + * contained within an instance of this class to synchronize with an LE Audio Broadcast Source in + * order to listen to a Broadcast Audio Stream. + * + *
BroadcastAssistant has a BASS client which facilitates scanning and discovery of Broadcast + * Sources on behalf of say a Broadcast Sink. Upon successful discovery of one or more Broadcast + * sources, this information needs to be communicated to the BASS Server residing within the Scan + * Delegator on a Broadcast Sink. This is achieved using the Periodic Advertising Synchronization + * Transfer (PAST) procedure. This procedure uses information contained within an instance of this + * class. + * + * @hide + */ +public final class BluetoothLeBroadcastSourceInfo implements Parcelable { + private static final String TAG = "BluetoothLeBroadcastSourceInfo"; + private static final boolean DBG = true; + + /** + * Constants representing Broadcast Source address types + * + * @hide + */ + @IntDef( + prefix = "LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_", + value = { + LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_PUBLIC, + LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_RANDOM, + LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LeAudioBroadcastSourceAddressType {} + + /** + * Represents a public address used by an LE Audio Broadcast Source + * + * @hide + */ + public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_PUBLIC = 0; + + /** + * Represents a random address used by an LE Audio Broadcast Source + * + * @hide + */ + public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_RANDOM = 1; + + /** + * Represents an invalid address used by an LE Audio Broadcast Seurce + * + * @hide + */ + public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID = 0xFFFF; + + /** + * Periodic Advertising Synchronization state + * + *
Periodic Advertising (PA) enables the LE Audio Broadcast Assistant to discover broadcast + * audio streams as well as the audio stream configuration on behalf of an LE Audio Broadcast + * Sink. This information can then be transferred to the LE Audio Broadcast Sink using the + * Periodic Advertising Synchronizaton Transfer (PAST) procedure. + * + * @hide + */ + @IntDef( + prefix = "LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_", + value = { + LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IDLE, + LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNCINFO_REQ, + LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IN_SYNC, + LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNC_FAIL, + LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_NO_PAST + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LeAudioBroadcastSinkPaSyncState {} + + /** + * Indicates that the Broadcast Sink is not synchronized with the Periodic Advertisements (PA) + * + * @hide + */ + public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IDLE = 0; + + /** + * Indicates that the Broadcast Sink requested the Broadcast Assistant to synchronize with the + * Periodic Advertisements (PA). + * + *
This is also known as scan delegation or scan offloading.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNCINFO_REQ = 1;
+
+ /**
+ * Indicates that the Broadcast Sink is synchronized with the Periodic Advertisements (PA).
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IN_SYNC = 2;
+
+ /**
+ * Indicates that the Broadcast Sink was unable to synchronize with the Periodic Advertisements
+ * (PA).
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNC_FAIL = 3;
+
+ /**
+ * Indicates that the Broadcast Sink should be synchronized with the Periodic Advertisements
+ * (PA) using the Periodic Advertisements Synchronization Transfert (PAST) procedure.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_NO_PAST = 4;
+
+ /**
+ * Indicates that the Broadcast Sink synchornization state is invalid.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID = 0xFFFF;
+
+ /** @hide */
+ @IntDef(
+ prefix = "LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_",
+ value = {
+ LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED,
+ LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_SYNCHRONIZED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LeAudioBroadcastSinkAudioSyncState {}
+
+ /**
+ * Indicates that the Broadcast Sink is not synchronized with a Broadcast Audio Stream.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED = 0;
+
+ /**
+ * Indicates that the Broadcast Sink is synchronized with a Broadcast Audio Stream.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_SYNCHRONIZED = 1;
+
+ /**
+ * Indicates that the Broadcast Sink audio synchronization state is invalid.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID = 0xFFFF;
+
+ /** @hide */
+ @IntDef(
+ prefix = "LE_AUDIO_BROADCAST_SINK_ENC_STATE_",
+ value = {
+ LE_AUDIO_BROADCAST_SINK_ENC_STATE_NOT_ENCRYPTED,
+ LE_AUDIO_BROADCAST_SINK_ENC_STATE_CODE_REQUIRED,
+ LE_AUDIO_BROADCAST_SINK_ENC_STATE_DECRYPTING,
+ LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LeAudioBroadcastSinkEncryptionState {}
+
+ /**
+ * Indicates that the Broadcast Sink is synchronized with an unencrypted audio stream.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_NOT_ENCRYPTED = 0;
+
+ /**
+ * Indicates that the Broadcast Sink needs a Broadcast Code to synchronize with the audio
+ * stream.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_CODE_REQUIRED = 1;
+
+ /**
+ * Indicates that the Broadcast Sink is synchronized with an encrypted audio stream.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_DECRYPTING = 2;
+
+ /**
+ * Indicates that the Broadcast Sink is unable to decrypt an audio stream due to an incorrect
+ * Broadcast Code
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE = 3;
+
+ /**
+ * Indicates that the Broadcast Sink encryption state is invalid.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID = 0xFF;
+
+ /**
+ * Represents an invalid LE Audio Broadcast Source ID
+ *
+ * @hide
+ */
+ public static final byte LE_AUDIO_BROADCAST_SINK_INVALID_SOURCE_ID = (byte) 0x00;
+
+ /**
+ * Represents an invalid Broadcast ID of a Broadcast Source
+ *
+ * @hide
+ */
+ public static final int INVALID_BROADCAST_ID = 0xFFFFFF;
+
+ private byte mSourceId;
+ private @LeAudioBroadcastSourceAddressType int mSourceAddressType;
+ private BluetoothDevice mSourceDevice;
+ private byte mSourceAdvSid;
+ private int mBroadcastId;
+ private @LeAudioBroadcastSinkPaSyncState int mPaSyncState;
+ private @LeAudioBroadcastSinkEncryptionState int mEncryptionStatus;
+ private @LeAudioBroadcastSinkAudioSyncState int mAudioSyncState;
+ private byte[] mBadBroadcastCode;
+ private byte mNumSubGroups;
+ private Map This is mainly used to represent the Empty Broadcast Source entries
+ *
+ * @param sourceId Source Id for this Broadcast Source info object
+ * @hide
+ */
+ public BluetoothLeBroadcastSourceInfo(byte sourceId) {
+ mSourceId = sourceId;
+ mSourceAddressType = LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID;
+ mSourceDevice = null;
+ mSourceAdvSid = (byte) 0x00;
+ mBroadcastId = INVALID_BROADCAST_ID;
+ mPaSyncState = LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID;
+ mAudioSyncState = LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID;
+ mEncryptionStatus = LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID;
+ mBadBroadcastCode = null;
+ mNumSubGroups = 0;
+ mBroadcastCode = null;
+ }
+
+ /*package*/ BluetoothLeBroadcastSourceInfo(
+ byte sourceId,
+ @LeAudioBroadcastSourceAddressType int addressType,
+ @NonNull BluetoothDevice device,
+ byte advSid,
+ int broadcastId,
+ @LeAudioBroadcastSinkPaSyncState int paSyncstate,
+ @LeAudioBroadcastSinkEncryptionState int encryptionStatus,
+ @LeAudioBroadcastSinkAudioSyncState int audioSyncstate,
+ @Nullable byte[] badCode,
+ byte numSubGroups,
+ @NonNull Map This code is valid only if {@link #getEncryptionStatus} returns {@link
+ * #LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE}
+ *
+ * @return byte array containing bad broadcast value, null if the current encryption status is
+ * not {@link #LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE}
+ * @hide
+ */
+ public @Nullable byte[] getBadBroadcastCode() {
+ return mBadBroadcastCode;
+ }
+
+ /**
+ * Get the number of subgroups.
+ *
+ * @return number of subgroups
+ * @hide
+ */
+ public byte getNumberOfSubGroups() {
+ return mNumSubGroups;
+ }
+
+ public @NonNull Map