Merge "Add BluetoothLeBroadcastSourceInfo."

This commit is contained in:
Treehugger Robot
2022-01-06 10:32:39 +00:00
committed by Gerrit Code Review

View File

@@ -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.
*
* <p>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.
*
* <p>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
*
* <p>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).
*
* <p>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<Integer, Integer> mSubgroupBisSyncState = new HashMap<Integer, Integer>();
private Map<Integer, byte[]> mSubgroupMetadata = new HashMap<Integer, byte[]>();
private String mBroadcastCode;
private static final int BIS_NO_PREF = 0xFFFFFFFF;
private static final int BROADCAST_CODE_SIZE = 16;
/**
* Constructor to create an Empty object of {@link BluetoothLeBroadcastSourceInfo } with the
* given Source Id.
*
* <p>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<Integer, Integer> bisSyncState,
@Nullable Map<Integer, byte[]> subgroupMetadata,
@NonNull String broadcastCode) {
mSourceId = sourceId;
mSourceAddressType = addressType;
mSourceDevice = device;
mSourceAdvSid = advSid;
mBroadcastId = broadcastId;
mPaSyncState = paSyncstate;
mEncryptionStatus = encryptionStatus;
mAudioSyncState = audioSyncstate;
if (badCode != null && badCode.length != 0) {
mBadBroadcastCode = new byte[badCode.length];
System.arraycopy(badCode, 0, mBadBroadcastCode, 0, badCode.length);
}
mNumSubGroups = numSubGroups;
mSubgroupBisSyncState = new HashMap<Integer, Integer>(bisSyncState);
mSubgroupMetadata = new HashMap<Integer, byte[]>(subgroupMetadata);
mBroadcastCode = broadcastCode;
}
@Override
public boolean equals(Object o) {
if (o instanceof BluetoothLeBroadcastSourceInfo) {
BluetoothLeBroadcastSourceInfo other = (BluetoothLeBroadcastSourceInfo) o;
return (other.mSourceId == mSourceId
&& other.mSourceAddressType == mSourceAddressType
&& other.mSourceDevice == mSourceDevice
&& other.mSourceAdvSid == mSourceAdvSid
&& other.mBroadcastId == mBroadcastId
&& other.mPaSyncState == mPaSyncState
&& other.mEncryptionStatus == mEncryptionStatus
&& other.mAudioSyncState == mAudioSyncState
&& Arrays.equals(other.mBadBroadcastCode, mBadBroadcastCode)
&& other.mNumSubGroups == mNumSubGroups
&& mSubgroupBisSyncState.equals(other.mSubgroupBisSyncState)
&& mSubgroupMetadata.equals(other.mSubgroupMetadata)
&& other.mBroadcastCode == mBroadcastCode);
}
return false;
}
/**
* Checks if an instance of {@link BluetoothLeBroadcastSourceInfo} is empty.
*
* @hide
*/
public boolean isEmpty() {
boolean ret = false;
if (mSourceAddressType == LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID
&& mSourceDevice == null
&& mSourceAdvSid == (byte) 0
&& mPaSyncState == LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID
&& mEncryptionStatus == LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID
&& mAudioSyncState == LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID
&& mBadBroadcastCode == null
&& mNumSubGroups == 0
&& mSubgroupBisSyncState.size() == 0
&& mSubgroupMetadata.size() == 0
&& mBroadcastCode == null) {
ret = true;
}
return ret;
}
/**
* Compares an instance of {@link BluetoothLeBroadcastSourceInfo} with the provided instance.
*
* @hide
*/
public boolean matches(BluetoothLeBroadcastSourceInfo srcInfo) {
boolean ret = false;
if (srcInfo == null) {
ret = false;
} else {
if (mSourceDevice == null) {
if (mSourceAdvSid == srcInfo.getAdvertisingSid()
&& mSourceAddressType == srcInfo.getAdvAddressType()) {
ret = true;
}
} else {
if (mSourceDevice.equals(srcInfo.getSourceDevice())
&& mSourceAdvSid == srcInfo.getAdvertisingSid()
&& mSourceAddressType == srcInfo.getAdvAddressType()
&& mBroadcastId == srcInfo.getBroadcastId()) {
ret = true;
}
}
}
return ret;
}
@Override
public int hashCode() {
return Objects.hash(
mSourceId,
mSourceAddressType,
mSourceDevice,
mSourceAdvSid,
mBroadcastId,
mPaSyncState,
mEncryptionStatus,
mAudioSyncState,
mBadBroadcastCode,
mNumSubGroups,
mSubgroupBisSyncState,
mSubgroupMetadata,
mBroadcastCode);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "{BluetoothLeBroadcastSourceInfo : mSourceId"
+ mSourceId
+ " addressType: "
+ mSourceAddressType
+ " sourceDevice: "
+ mSourceDevice
+ " mSourceAdvSid:"
+ mSourceAdvSid
+ " mBroadcastId:"
+ mBroadcastId
+ " mPaSyncState:"
+ mPaSyncState
+ " mEncryptionStatus:"
+ mEncryptionStatus
+ " mAudioSyncState:"
+ mAudioSyncState
+ " mBadBroadcastCode:"
+ mBadBroadcastCode
+ " mNumSubGroups:"
+ mNumSubGroups
+ " mSubgroupBisSyncState:"
+ mSubgroupBisSyncState
+ " mSubgroupMetadata:"
+ mSubgroupMetadata
+ " mBroadcastCode:"
+ mBroadcastCode
+ "}";
}
/**
* Get the Source Id
*
* @return byte representing the Source Id, {@link
* #LE_AUDIO_BROADCAST_ASSISTANT_INVALID_SOURCE_ID} if invalid
* @hide
*/
public byte getSourceId() {
return mSourceId;
}
/**
* Set the Source Id
*
* @param sourceId source Id
* @hide
*/
public void setSourceId(byte sourceId) {
mSourceId = sourceId;
}
/**
* Set the Broadcast Source device
*
* @param sourceDevice the Broadcast Source BluetoothDevice
* @hide
*/
public void setSourceDevice(@NonNull BluetoothDevice sourceDevice) {
mSourceDevice = sourceDevice;
}
/**
* Get the Broadcast Source BluetoothDevice
*
* @return Broadcast Source BluetoothDevice
* @hide
*/
public @NonNull BluetoothDevice getSourceDevice() {
return mSourceDevice;
}
/**
* Set the address type of the Broadcast Source advertisements
*
* @hide
*/
public void setAdvAddressType(@LeAudioBroadcastSourceAddressType int addressType) {
mSourceAddressType = addressType;
}
/**
* Get the address type used by advertisements from the Broadcast Source.
* BluetoothLeBroadcastSourceInfo Object
*
* @hide
*/
@LeAudioBroadcastSourceAddressType
public int getAdvAddressType() {
return mSourceAddressType;
}
/**
* Set the advertising SID of the Broadcast Source advertisement.
*
* @param advSid advertising SID of the Broadcast Source
* @hide
*/
public void setAdvertisingSid(byte advSid) {
mSourceAdvSid = advSid;
}
/**
* Get the advertising SID of the Broadcast Source advertisement.
*
* @return advertising SID of the Broadcast Source
* @hide
*/
public byte getAdvertisingSid() {
return mSourceAdvSid;
}
/**
* Get the Broadcast ID of the Broadcast Source.
*
* @return broadcast ID
* @hide
*/
public int getBroadcastId() {
return mBroadcastId;
}
/**
* Set the Periodic Advertising (PA) Sync State.
*
* @hide
*/
/*package*/ void setPaSyncState(@LeAudioBroadcastSinkPaSyncState int paSyncState) {
mPaSyncState = paSyncState;
}
/**
* Get the Periodic Advertising (PA) Sync State
*
* @hide
*/
public @LeAudioBroadcastSinkPaSyncState int getMetadataSyncState() {
return mPaSyncState;
}
/**
* Set the audio sync state
*
* @hide
*/
/*package*/ void setAudioSyncState(@LeAudioBroadcastSinkAudioSyncState int audioSyncState) {
mAudioSyncState = audioSyncState;
}
/**
* Get the audio sync state
*
* @hide
*/
public @LeAudioBroadcastSinkAudioSyncState int getAudioSyncState() {
return mAudioSyncState;
}
/**
* Set the encryption status
*
* @hide
*/
/*package*/ void setEncryptionStatus(
@LeAudioBroadcastSinkEncryptionState int encryptionStatus) {
mEncryptionStatus = encryptionStatus;
}
/**
* Get the encryption status
*
* @hide
*/
public @LeAudioBroadcastSinkEncryptionState int getEncryptionStatus() {
return mEncryptionStatus;
}
/**
* Get the incorrect broadcast code that the Scan delegator used to decrypt the Broadcast Audio
* Stream and failed.
*
* <p>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<Integer, Integer> getSubgroupBisSyncState() {
return mSubgroupBisSyncState;
}
public void setSubgroupBisSyncState(@NonNull Map<Integer, Integer> bisSyncState) {
mSubgroupBisSyncState = new HashMap<Integer, Integer>(bisSyncState);
}
/*package*/ void setBroadcastCode(@NonNull String broadcastCode) {
mBroadcastCode = broadcastCode;
}
/**
* Get the broadcast code
*
* @return
* @hide
*/
public @NonNull String getBroadcastCode() {
return mBroadcastCode;
}
/**
* Set the broadcast ID
*
* @param broadcastId broadcast ID of the Broadcast Source
* @hide
*/
public void setBroadcastId(int broadcastId) {
mBroadcastId = broadcastId;
}
private void writeSubgroupBisSyncStateToParcel(
@NonNull Parcel dest, @NonNull Map<Integer, Integer> subgroupBisSyncState) {
dest.writeInt(subgroupBisSyncState.size());
for (Map.Entry<Integer, Integer> entry : subgroupBisSyncState.entrySet()) {
dest.writeInt(entry.getKey());
dest.writeInt(entry.getValue());
}
}
private static void readSubgroupBisSyncStateFromParcel(
@NonNull Parcel in, @NonNull Map<Integer, Integer> subgroupBisSyncState) {
int size = in.readInt();
for (int i = 0; i < size; i++) {
Integer key = in.readInt();
Integer value = in.readInt();
subgroupBisSyncState.put(key, value);
}
}
private void writeSubgroupMetadataToParcel(
@NonNull Parcel dest, @Nullable Map<Integer, byte[]> subgroupMetadata) {
if (subgroupMetadata == null) {
dest.writeInt(0);
return;
}
dest.writeInt(subgroupMetadata.size());
for (Map.Entry<Integer, byte[]> entry : subgroupMetadata.entrySet()) {
dest.writeInt(entry.getKey());
byte[] metadata = entry.getValue();
if (metadata != null) {
dest.writeInt(metadata.length);
dest.writeByteArray(metadata);
}
}
}
private static void readSubgroupMetadataFromParcel(
@NonNull Parcel in, @NonNull Map<Integer, byte[]> subgroupMetadata) {
int size = in.readInt();
for (int i = 0; i < size; i++) {
Integer key = in.readInt();
Integer metaDataLen = in.readInt();
byte[] metadata = null;
if (metaDataLen != 0) {
metadata = new byte[metaDataLen];
in.readByteArray(metadata);
}
subgroupMetadata.put(key, metadata);
}
}
public static final @NonNull Parcelable.Creator<BluetoothLeBroadcastSourceInfo> CREATOR =
new Parcelable.Creator<BluetoothLeBroadcastSourceInfo>() {
public @NonNull BluetoothLeBroadcastSourceInfo createFromParcel(
@NonNull Parcel in) {
final byte sourceId = in.readByte();
final int sourceAddressType = in.readInt();
final BluetoothDevice sourceDevice =
in.readTypedObject(BluetoothDevice.CREATOR);
final byte sourceAdvSid = in.readByte();
final int broadcastId = in.readInt();
final int paSyncState = in.readInt();
final int audioSyncState = in.readInt();
final int encryptionStatus = in.readInt();
final int badBroadcastLen = in.readInt();
byte[] badBroadcastCode = null;
if (badBroadcastLen > 0) {
badBroadcastCode = new byte[badBroadcastLen];
in.readByteArray(badBroadcastCode);
}
final byte numSubGroups = in.readByte();
final String broadcastCode = in.readString();
Map<Integer, Integer> subgroupBisSyncState = new HashMap<Integer, Integer>();
readSubgroupBisSyncStateFromParcel(in, subgroupBisSyncState);
Map<Integer, byte[]> subgroupMetadata = new HashMap<Integer, byte[]>();
readSubgroupMetadataFromParcel(in, subgroupMetadata);
BluetoothLeBroadcastSourceInfo srcInfo =
new BluetoothLeBroadcastSourceInfo(
sourceId,
sourceAddressType,
sourceDevice,
sourceAdvSid,
broadcastId,
paSyncState,
encryptionStatus,
audioSyncState,
badBroadcastCode,
numSubGroups,
subgroupBisSyncState,
subgroupMetadata,
broadcastCode);
return srcInfo;
}
public @NonNull BluetoothLeBroadcastSourceInfo[] newArray(int size) {
return new BluetoothLeBroadcastSourceInfo[size];
}
};
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeByte(mSourceId);
out.writeInt(mSourceAddressType);
out.writeTypedObject(mSourceDevice, 0);
out.writeByte(mSourceAdvSid);
out.writeInt(mBroadcastId);
out.writeInt(mPaSyncState);
out.writeInt(mAudioSyncState);
out.writeInt(mEncryptionStatus);
if (mBadBroadcastCode != null) {
out.writeInt(mBadBroadcastCode.length);
out.writeByteArray(mBadBroadcastCode);
} else {
// zero indicates that there is no "bad broadcast code"
out.writeInt(0);
}
out.writeByte(mNumSubGroups);
out.writeString(mBroadcastCode);
writeSubgroupBisSyncStateToParcel(out, mSubgroupBisSyncState);
writeSubgroupMetadataToParcel(out, mSubgroupMetadata);
}
private static void log(@NonNull String msg) {
if (DBG) {
Log.d(TAG, msg);
}
}
}
;