/* * 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