diff options
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java')
-rw-r--r-- | framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java new file mode 100644 index 0000000000..1810818c98 --- /dev/null +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java @@ -0,0 +1,486 @@ +/* + * 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.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; + +/** + * 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. + * + * <p>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 byte[] mBroadcastCode; + + // 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<BluetoothLeBroadcastSubgroup> mSubgroups; + + private BluetoothLeBroadcastMetadata(int sourceAddressType, + BluetoothDevice sourceDevice, int sourceAdvertisingSid, int broadcastId, + int paSyncInterval, boolean isEncrypted, byte[] broadcastCode, int presentationDelay, + List<BluetoothLeBroadcastSubgroup> subgroups) { + mSourceAddressType = sourceAddressType; + mSourceDevice = sourceDevice; + mSourceAdvertisingSid = sourceAdvertisingSid; + mBroadcastId = broadcastId; + mPaSyncInterval = paSyncInterval; + mIsEncrypted = isEncrypted; + mBroadcastCode = broadcastCode; + mPresentationDelayMicros = presentationDelay; + mSubgroups = subgroups; + } + + /** + * Get the address type of the Broadcast Source. + * + * Can be either {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}, + * {@link BluetoothDevice#ADDRESS_TYPE_RANDOM} + * + * @return address type of the Broadcast Source + * @hide + */ + @SystemApi + public @BluetoothDevice.AddressType int getSourceAddressType() { + return mSourceAddressType; + } + + /** + * Get the MAC address of the Broadcast Source, which can be Public Device Address, + * Random Device Address, Public Identity Address or Random (static) Identity Address. + * + * @return MAC address of the Broadcast Source + * @hide + */ + @SystemApi + public @Nullable BluetoothDevice getSourceDevice() { + return mSourceDevice; + } + + /** + * Get Advertising_SID subfield of the ADI field of the AUX_ADV_IND PDU or the + * LL_PERIODIC_SYNC_IND containing the SyncInfo that points to the PA transmitted by the + * Broadcast Source. + * + * @return 1-byte long Advertising_SID of the Broadcast Source + * @hide + */ + @SystemApi + public int getSourceAdvertisingSid() { + return mSourceAdvertisingSid; + } + + /** + * Broadcast_ID of the Broadcast Source. + * + * @return 3-byte long Broadcast_ID of the Broadcast Source + * @hide + */ + @SystemApi + public int getBroadcastId() { + return mBroadcastId; + } + + /** + * Indicated that Periodic Advertising Sync interval is unknown. + * @hide + */ + @SystemApi + public static final int PA_SYNC_INTERVAL_UNKNOWN = 0xFFFF; + + /** + * Get Periodic Advertising Sync interval of the broadcast Source. + * + * @return Periodic Advertising Sync interval of the broadcast Source, + * {@link #PA_SYNC_INTERVAL_UNKNOWN} if unknown + * @hide + */ + @SystemApi + public int getPaSyncInterval() { + return mPaSyncInterval; + } + + /** + * Return true if the Broadcast Source is encrypted. + * + * @return true if the Broadcast Source is encrypted + * @hide + */ + @SystemApi + public boolean isEncrypted() { + return mIsEncrypted; + } + + /** + * Get the Broadcast Code currently set for this Broadcast Source. + * + * Only needed when encryption is enabled + * + * <p>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. + * <p>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, 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 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<BluetoothLeBroadcastSubgroup> getSubgroups() { + return mSubgroups; + } + + /** + * {@inheritDoc} + * @hide + */ + @Override + public int describeContents() { + return 0; + } + + /** + * {@inheritDoc} + * @hide + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mSourceAddressType); + if (mSourceDevice != null) { + out.writeInt(1); + out.writeTypedObject(mSourceDevice, 0); + } else { + // zero indicates missing mSourceDevice + out.writeInt(0); + } + out.writeInt(mSourceAdvertisingSid); + out.writeInt(mBroadcastId); + out.writeInt(mPaSyncInterval); + out.writeBoolean(mIsEncrypted); + if (mBroadcastCode != null) { + out.writeInt(mBroadcastCode.length); + out.writeByteArray(mBroadcastCode); + } else { + // -1 indicates missing broadcast code + out.writeInt(-1); + } + out.writeInt(mPresentationDelayMicros); + out.writeTypedList(mSubgroups); + } + + /** + * A {@link Parcelable.Creator} to create {@link BluetoothLeBroadcastMetadata} from parcel. + * @hide + */ + @SystemApi + public static final @NonNull Parcelable.Creator<BluetoothLeBroadcastMetadata> CREATOR = + new Parcelable.Creator<BluetoothLeBroadcastMetadata>() { + public @NonNull BluetoothLeBroadcastMetadata createFromParcel(@NonNull Parcel in) { + Builder builder = new Builder(); + final int sourceAddressType = in.readInt(); + final int deviceExist = in.readInt(); + BluetoothDevice sourceDevice = null; + if (deviceExist == 1) { + sourceDevice = in.readTypedObject(BluetoothDevice.CREATOR); + } + builder.setSourceDevice(sourceDevice, sourceAddressType); + builder.setSourceAdvertisingSid(in.readInt()); + builder.setBroadcastId(in.readInt()); + builder.setPaSyncInterval(in.readInt()); + builder.setEncrypted(in.readBoolean()); + final int codeLen = in.readInt(); + byte[] broadcastCode = null; + if (codeLen != -1) { + broadcastCode = new byte[codeLen]; + if (codeLen > 0) { + in.readByteArray(broadcastCode); + } + } + builder.setBroadcastCode(broadcastCode); + builder.setPresentationDelayMicros(in.readInt()); + final List<BluetoothLeBroadcastSubgroup> subgroups = new ArrayList<>(); + in.readTypedList(subgroups, BluetoothLeBroadcastSubgroup.CREATOR); + for (BluetoothLeBroadcastSubgroup subgroup : subgroups) { + builder.addSubgroup(subgroup); + } + return builder.build(); + } + + public @NonNull BluetoothLeBroadcastMetadata[] newArray(int size) { + return new BluetoothLeBroadcastMetadata[size]; + } + }; + + private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; + + /** + * Builder for {@link BluetoothLeBroadcastMetadata}. + * @hide + */ + @SystemApi + public static final class Builder { + private @BluetoothDevice.AddressType int mSourceAddressType = + BluetoothDevice.ADDRESS_TYPE_UNKNOWN; + private BluetoothDevice mSourceDevice = null; + private int mSourceAdvertisingSid = UNKNOWN_VALUE_PLACEHOLDER; + private int mBroadcastId = UNKNOWN_VALUE_PLACEHOLDER; + private int mPaSyncInterval = UNKNOWN_VALUE_PLACEHOLDER; + private boolean mIsEncrypted = false; + private byte[] mBroadcastCode = null; + private int mPresentationDelayMicros = UNKNOWN_VALUE_PLACEHOLDER; + private List<BluetoothLeBroadcastSubgroup> mSubgroups = new ArrayList<>(); + + /** + * Create an empty builder. + * @hide + */ + @SystemApi + public Builder() {} + + /** + * Create a builder with copies of information from original object. + * + * @param original original object + * @hide + */ + @SystemApi + public Builder(@NonNull BluetoothLeBroadcastMetadata original) { + mSourceAddressType = original.getSourceAddressType(); + mSourceDevice = original.getSourceDevice(); + mSourceAdvertisingSid = original.getSourceAdvertisingSid(); + mBroadcastId = original.getBroadcastId(); + mPaSyncInterval = original.getPaSyncInterval(); + mIsEncrypted = original.isEncrypted(); + mBroadcastCode = original.getBroadcastCode(); + mPresentationDelayMicros = original.getPresentationDelayMicros(); + mSubgroups = original.getSubgroups(); + } + + + /** + * Set the address type and MAC address of the Broadcast Source. + * + * Address type can be either {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}, + * {@link BluetoothDevice#ADDRESS_TYPE_RANDOM} + * + * MAC address can be Public Device Address, Random Device Address, Public Identity Address + * or Random (static) Identity Address + * + * @param sourceDevice source advertiser address + * @param sourceAddressType source advertiser address type + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder setSourceDevice(@Nullable BluetoothDevice sourceDevice, + @BluetoothDevice.AddressType int sourceAddressType) { + mSourceDevice = sourceDevice; + mSourceAddressType = sourceAddressType; + return this; + } + + /** + * Set Advertising_SID that is a subfield of the ADI field of the AUX_ADV_IND PDU or the + * LL_PERIODIC_SYNC_IND containing the SyncInfo that points to the PA transmitted by the + * Broadcast Source. + * + * @param sourceAdvertisingSid 1-byte long Advertising_SID of the Broadcast Source + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder setSourceAdvertisingSid(int sourceAdvertisingSid) { + mSourceAdvertisingSid = sourceAdvertisingSid; + return this; + } + + /** + * Set the Broadcast_ID of the Broadcast Source. + * + * @param broadcastId 3-byte long Broadcast_ID of the Broadcast Source + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder setBroadcastId(int broadcastId) { + mBroadcastId = broadcastId; + return this; + } + + /** + * Set Periodic Advertising Sync interval of the broadcast Source. + * + * @param paSyncInterval Periodic Advertising Sync interval of the broadcast Source, + * {@link #PA_SYNC_INTERVAL_UNKNOWN} if unknown + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder setPaSyncInterval(int paSyncInterval) { + mPaSyncInterval = paSyncInterval; + return this; + } + + /** + * Set whether the Broadcast Source should be encrypted. + * + * When setting up a Broadcast Source, if <var>isEncrypted</var> is true while + * <var>broadcastCode</var> is null, the implementation will automatically generate + * a Broadcast Code + * + * @param isEncrypted whether the Broadcast Source is encrypted + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder setEncrypted(boolean isEncrypted) { + mIsEncrypted = isEncrypted; + return this; + } + + /** + * Set the Broadcast Code currently set for this Broadcast Source. + * + * Only needed when encryption is enabled + * + * <p>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. + * <p>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, 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 + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder setPresentationDelayMicros( + @IntRange(from = 0, to = 0xFFFFFF) int presentationDelayMicros) { + mPresentationDelayMicros = presentationDelayMicros; + return this; + } + + /** + * Add a subgroup to this broadcast source. + * + * @param subgroup {@link BluetoothLeBroadcastSubgroup} that contains a subgroup's metadata + * @return this builder + * @hide + */ + @SystemApi + public @NonNull Builder addSubgroup(@NonNull BluetoothLeBroadcastSubgroup subgroup) { + 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 + * @hide + */ + @SystemApi + public @NonNull BluetoothLeBroadcastMetadata build() { + return new BluetoothLeBroadcastMetadata(mSourceAddressType, mSourceDevice, + mSourceAdvertisingSid, mBroadcastId, mPaSyncInterval, mIsEncrypted, + mBroadcastCode, mPresentationDelayMicros, mSubgroups); + } + } +} |