/* * Copyright 2022 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.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; /** * This class represents a Broadcast Source group and the associated information that is needed * by Broadcast Audio Scan Service (BASS) to set up a Broadcast Sink. * *
For example, an LE Audio Broadcast Sink can use the information contained within an instance
* of this class to synchronize with an LE Audio Broadcast group in order to listen to audio from
* Broadcast subgroup using one or more Broadcast Channels.
*
* @hide
*/
@SystemApi
public final class BluetoothLeBroadcastMetadata implements Parcelable {
// Information needed for adding broadcast Source
// Optional: Identity address type
private final @BluetoothDevice.AddressType int mSourceAddressType;
// Optional: Must use identity address
private final BluetoothDevice mSourceDevice;
private final int mSourceAdvertisingSid;
private final int mBroadcastId;
private final int mPaSyncInterval;
private final boolean mIsEncrypted;
private final boolean mIsPublicBroadcast;
private final String mBroadcastName;
private final byte[] mBroadcastCode;
private final BluetoothLeAudioContentMetadata mPublicBroadcastMetadata;
private final @AudioConfigQuality int mAudioConfigQuality;
/**
* Audio configuration quality for this Broadcast Group.
* This quality bitmap is used for presenting the audio stream quality for this BIG,
* either public broadcast or non-public broadcast
* Bit0 indicates at least one broadcast Audio Stream configuration is standard quality
* Bit1 indicates at least one broadcast Audio Stream configuration is high quality
*
* @hide
*/
@IntDef(flag = true, prefix = "AUDIO_CONFIG_QUALITY_",
value = {
AUDIO_CONFIG_QUALITY_NONE,
AUDIO_CONFIG_QUALITY_STANDARD,
AUDIO_CONFIG_QUALITY_HIGH,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AudioConfigQuality {}
/**
* Audio config quality is none, default value used for audio config quality.
*
* @hide
*/
@SystemApi
public static final int AUDIO_CONFIG_QUALITY_NONE = 0;
/**
* Audio config quality is standard.
* This indicates the BIG shall include at least one broadcast Audio Stream
* configuration defined as Mandatory for a Broadcast Sink in
* Basic Audio Profile, Version 1 or later, table 6.4
*
* @hide
*/
@SystemApi
public static final int AUDIO_CONFIG_QUALITY_STANDARD = 0x1 << 0;
/**
* Audio config quality is standard.
* This indicates the BIG shall include at least one broadcast Audio Stream
* configuration setting listed in
* Public Broadcast Profile, Version 1 or later, table 4.2
*
* @hide
*/
@SystemApi
public static final int AUDIO_CONFIG_QUALITY_HIGH = 0x1 << 1;
// BASE structure
// See Section 7 for description. Range: 0x000000 – 0xFFFFFF Units: μs
//All other values: RFU
private final int mPresentationDelayMicros;
// Number of subgroups used to group BISes present in the BIG
//Shall be at least 1, as defined by Rule 1
// Sub group info numSubGroup = mSubGroups.length
private final List As defined in Volume 3, Part C, Section 3.2.6 of Bluetooth Core Specification, Version
* 5.3, Broadcast Code is used to encrypt a broadcast audio stream.
* It must be a UTF-8 string that has at least 4 octets and should not exceed 16 octets.
*
* @return Broadcast Code currently set for this Broadcast Source,
* {@code null} if code is not required
* or code is currently unknown
* @hide
*/
@SystemApi
public @Nullable byte[] getBroadcastCode() {
return mBroadcastCode;
}
/**
* Get the overall presentation delay in microseconds of this Broadcast Source.
*
* Presentation delay is defined in Section 7 of the Basic Audio Profile.
*
* @return presentation delay of this Broadcast Source in microseconds
* @hide
*/
@SystemApi
public @IntRange(from = 0, to = 0xFFFFFF) int getPresentationDelayMicros() {
return mPresentationDelayMicros;
}
/**
* Get broadcast audio config quality for this Broadcast Group.
*
* @return Broadcast audio config quality for this Broadcast Group
* @hide
*/
@SystemApi
public @AudioConfigQuality int getAudioConfigQuality() {
return mAudioConfigQuality;
}
/**
* Get public broadcast metadata for this Broadcast Group.
*
* @return public broadcast metadata for this Broadcast Group,
* {@code null} if no public metadata exists
* @hide
*/
@SystemApi
public @Nullable BluetoothLeAudioContentMetadata getPublicBroadcastMetadata() {
return mPublicBroadcastMetadata;
}
/**
* Get available subgroups in this broadcast source.
*
* @return list of subgroups in this broadcast source, which should contain at least one
* subgroup for each Broadcast Source
* @hide
*/
@SystemApi
public @NonNull List As defined in Volume 3, Part C, Section 3.2.6 of Bluetooth Core Specification, Version
* 5.3, Broadcast Code is used to encrypt a broadcast audio stream.
* It must be a UTF-8 string that has at least 4 octets and should not exceed 16 octets.
*
* @param broadcastCode Broadcast Code for this Broadcast Source,
* {@code null} if code is not required
* @return this builder
* @hide
*/
@SystemApi
public @NonNull Builder setBroadcastCode(@Nullable byte[] broadcastCode) {
mBroadcastCode = broadcastCode;
return this;
}
/**
* Set the overall presentation delay in microseconds of this Broadcast Source.
*
* Presentation delay is defined in Section 7 of the Basic Audio Profile.
*
* @param presentationDelayMicros presentation delay of this Broadcast Source in
* microseconds
* @throws IllegalArgumentException if presentationDelayMicros does not fall in
* [0, 0xFFFFFF]
* @return this builder
* @hide
*/
@SystemApi
@NonNull
public Builder setPresentationDelayMicros(
@IntRange(from = 0, to = 0xFFFFFF) int presentationDelayMicros) {
if (presentationDelayMicros < 0 || presentationDelayMicros >= 0xFFFFFF) {
throw new IllegalArgumentException("presentationDelayMicros "
+ presentationDelayMicros + " does not fall in [0, 0xFFFFFF]");
}
mPresentationDelayMicros = presentationDelayMicros;
return this;
}
/**
* Set broadcast audio config quality for this Broadcast Group.
*
* @param audioConfigQuality broadcast audio config quality for this Broadcast Group
* @return this builder
* @hide
*/
@SystemApi
@NonNull
public Builder setAudioConfigQuality(@AudioConfigQuality int audioConfigQuality) {
mAudioConfigQuality = audioConfigQuality;
return this;
}
/**
* Set public broadcast metadata for this Broadcast Group.
* PBS should include the Program_Info length-type-value (LTV) structure metadata
*
* @param publicBroadcastMetadata public broadcast metadata for this Broadcast Group,
{@code null} if no public meta data provided
* @return this builder
* @hide
*/
@SystemApi
@NonNull
public Builder setPublicBroadcastMetadata(
@Nullable BluetoothLeAudioContentMetadata publicBroadcastMetadata) {
mPublicBroadcastMetadata = publicBroadcastMetadata;
return this;
}
/**
* Add a subgroup to this broadcast source.
*
* @param subgroup {@link BluetoothLeBroadcastSubgroup} that contains a subgroup's metadata
* @throws NullPointerException if subgroup is null
* @return this builder
* @hide
*/
@SystemApi
public @NonNull Builder addSubgroup(@NonNull BluetoothLeBroadcastSubgroup subgroup) {
Objects.requireNonNull(subgroup, "subgroup cannot be null");
mSubgroups.add(subgroup);
return this;
}
/**
* Clear subgroup list so that one can reset the builder after create it from an existing
* object.
*
* @return this builder
* @hide
*/
@SystemApi
public @NonNull Builder clearSubgroup() {
mSubgroups.clear();
return this;
}
/**
* Build {@link BluetoothLeBroadcastMetadata}.
*
* @return {@link BluetoothLeBroadcastMetadata}
* @throws IllegalArgumentException if the object cannot be built
* @throws NullPointerException if {@link NonNull} items are null
* @hide
*/
@SystemApi
public @NonNull BluetoothLeBroadcastMetadata build() {
if (mSourceAddressType == BluetoothDevice.ADDRESS_TYPE_UNKNOWN) {
throw new IllegalArgumentException("SourceAddressTyp cannot be unknown");
}
if (mSourceAddressType != BluetoothDevice.ADDRESS_TYPE_RANDOM
&& mSourceAddressType != BluetoothDevice.ADDRESS_TYPE_PUBLIC) {
throw new IllegalArgumentException("sourceAddressType " + mSourceAddressType
+ " is invalid");
}
Objects.requireNonNull(mSourceDevice, "mSourceDevice cannot be null");
if (mSubgroups.isEmpty()) {
throw new IllegalArgumentException("Must contain at least one subgroup");
}
return new BluetoothLeBroadcastMetadata(mSourceAddressType, mSourceDevice,
mSourceAdvertisingSid, mBroadcastId, mPaSyncInterval, mIsEncrypted,
mIsPublicBroadcast, mBroadcastName, mBroadcastCode,
mPresentationDelayMicros, mAudioConfigQuality,
mPublicBroadcastMetadata, mSubgroups);
}
}
}