382 lines
13 KiB
Java
382 lines
13 KiB
Java
![]() |
/*
|
||
|
* Copyright 2023 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.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.annotation.SystemApi;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.List;
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/**
|
||
|
* This class contains the broadcast group settings information for this Broadcast Group.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public final class BluetoothLeBroadcastSettings implements Parcelable {
|
||
|
private final boolean mIsPublicBroadcast;
|
||
|
private final String mBroadcastName;
|
||
|
private final byte[] mBroadcastCode;
|
||
|
private final BluetoothLeAudioContentMetadata mPublicBroadcastMetadata;
|
||
|
private final List<BluetoothLeBroadcastSubgroupSettings> mSubgroupSettings;
|
||
|
|
||
|
private BluetoothLeBroadcastSettings(
|
||
|
boolean isPublicBroadcast,
|
||
|
String broadcastName,
|
||
|
byte[] broadcastCode,
|
||
|
BluetoothLeAudioContentMetadata publicBroadcastMetadata,
|
||
|
List<BluetoothLeBroadcastSubgroupSettings> subgroupSettings) {
|
||
|
mIsPublicBroadcast = isPublicBroadcast;
|
||
|
mBroadcastName = broadcastName;
|
||
|
mBroadcastCode = broadcastCode;
|
||
|
mPublicBroadcastMetadata = publicBroadcastMetadata;
|
||
|
mSubgroupSettings = subgroupSettings;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object o) {
|
||
|
if (!(o instanceof BluetoothLeBroadcastSettings)) {
|
||
|
return false;
|
||
|
}
|
||
|
final BluetoothLeBroadcastSettings other = (BluetoothLeBroadcastSettings) o;
|
||
|
return mIsPublicBroadcast == other.isPublicBroadcast()
|
||
|
&& Objects.equals(mBroadcastName, other.getBroadcastName())
|
||
|
&& Arrays.equals(mBroadcastCode, other.getBroadcastCode())
|
||
|
&& Objects.equals(mPublicBroadcastMetadata, other.getPublicBroadcastMetadata())
|
||
|
&& mSubgroupSettings.equals(other.getSubgroupSettings());
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(
|
||
|
mIsPublicBroadcast,
|
||
|
mBroadcastName,
|
||
|
Arrays.hashCode(mBroadcastCode),
|
||
|
mPublicBroadcastMetadata,
|
||
|
mSubgroupSettings);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return {@code true} if this Broadcast Group is set to broadcast Public Broadcast Announcement
|
||
|
* otherwise return {@code false}.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public boolean isPublicBroadcast() {
|
||
|
return mIsPublicBroadcast;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the broadcast code for this Broadcast Group.
|
||
|
*
|
||
|
* @return Broadcast name for this Broadcast Group, null if no name provided
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@Nullable
|
||
|
public String getBroadcastName() {
|
||
|
return mBroadcastName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the Broadcast Code currently set for this broadcast group.
|
||
|
*
|
||
|
* <p>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 group, null if code is not required
|
||
|
* or code is currently unknown
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@Nullable
|
||
|
public byte[] getBroadcastCode() {
|
||
|
return mBroadcastCode;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get public broadcast metadata for this Broadcast Group.
|
||
|
*
|
||
|
* @return public broadcast metadata for this Broadcast Group, null if no public metadata exists
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@Nullable
|
||
|
public BluetoothLeAudioContentMetadata getPublicBroadcastMetadata() {
|
||
|
return mPublicBroadcastMetadata;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get available subgroup settings in the broadcast group.
|
||
|
*
|
||
|
* @return list of subgroup settings in the broadcast group
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public List<BluetoothLeBroadcastSubgroupSettings> getSubgroupSettings() {
|
||
|
return mSubgroupSettings;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel out, int flags) {
|
||
|
out.writeBoolean(mIsPublicBroadcast);
|
||
|
out.writeString(mBroadcastName);
|
||
|
if (mBroadcastCode != null) {
|
||
|
out.writeInt(mBroadcastCode.length);
|
||
|
out.writeByteArray(mBroadcastCode);
|
||
|
} else {
|
||
|
// -1 indicates missing broadcast code
|
||
|
out.writeInt(-1);
|
||
|
}
|
||
|
out.writeTypedObject(mPublicBroadcastMetadata, 0);
|
||
|
out.writeTypedList(mSubgroupSettings);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A {@link Parcelable.Creator} to create {@link BluetoothLeBroadcastSettings} from parcel.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi @NonNull
|
||
|
public static final Creator<BluetoothLeBroadcastSettings> CREATOR =
|
||
|
new Creator<>() {
|
||
|
public @NonNull BluetoothLeBroadcastSettings createFromParcel(@NonNull Parcel in) {
|
||
|
Builder builder = new Builder();
|
||
|
builder.setPublicBroadcast(in.readBoolean());
|
||
|
builder.setBroadcastName(in.readString());
|
||
|
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.setPublicBroadcastMetadata(
|
||
|
in.readTypedObject(BluetoothLeAudioContentMetadata.CREATOR));
|
||
|
final List<BluetoothLeBroadcastSubgroupSettings> subgroupSettings =
|
||
|
new ArrayList<>();
|
||
|
in.readTypedList(
|
||
|
subgroupSettings, BluetoothLeBroadcastSubgroupSettings.CREATOR);
|
||
|
for (BluetoothLeBroadcastSubgroupSettings setting : subgroupSettings) {
|
||
|
builder.addSubgroupSettings(setting);
|
||
|
}
|
||
|
return builder.build();
|
||
|
}
|
||
|
|
||
|
public @NonNull BluetoothLeBroadcastSettings[] newArray(int size) {
|
||
|
return new BluetoothLeBroadcastSettings[size];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Builder for {@link BluetoothLeBroadcastSettings}.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public static final class Builder {
|
||
|
private boolean mIsPublicBroadcast = false;
|
||
|
private String mBroadcastName = null;
|
||
|
private byte[] mBroadcastCode = null;
|
||
|
private BluetoothLeAudioContentMetadata mPublicBroadcastMetadata = null;
|
||
|
private List<BluetoothLeBroadcastSubgroupSettings> mSubgroupSettings = 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 BluetoothLeBroadcastSettings original) {
|
||
|
mIsPublicBroadcast = original.isPublicBroadcast();
|
||
|
mBroadcastName = original.getBroadcastName();
|
||
|
mBroadcastCode = original.getBroadcastCode();
|
||
|
mPublicBroadcastMetadata = original.getPublicBroadcastMetadata();
|
||
|
mSubgroupSettings = original.getSubgroupSettings();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set whether the Public Broadcast is on for this broadcast group.
|
||
|
*
|
||
|
* @param isPublicBroadcast whether the Public Broadcast is enabled
|
||
|
* @return this builder
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public Builder setPublicBroadcast(boolean isPublicBroadcast) {
|
||
|
mIsPublicBroadcast = isPublicBroadcast;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set broadcast name for the broadcast group.
|
||
|
*
|
||
|
* <p>As defined in Public Broadcast Profile V1.0, section 5.1. Broadcast_Name AD Type is a
|
||
|
* UTF-8 encoded string containing a minimum of 4 characters and a maximum of 32
|
||
|
* human-readable characters.
|
||
|
*
|
||
|
* @param broadcastName Broadcast name for this broadcast group, null if no name provided
|
||
|
* @throws IllegalArgumentException if name is non-null and its length is less than 4
|
||
|
* characters or greater than 32 characters
|
||
|
* @return this builder
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public Builder setBroadcastName(@Nullable String broadcastName) {
|
||
|
if (broadcastName != null
|
||
|
&& ((broadcastName.length() > 32) || (broadcastName.length() < 4))) {
|
||
|
throw new IllegalArgumentException("Invalid broadcast name length");
|
||
|
}
|
||
|
mBroadcastName = broadcastName;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the Broadcast Code currently set for this broadcast group.
|
||
|
*
|
||
|
* <p>Only needed when encryption is enabled 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 group, null if code is not
|
||
|
* required for non-encrypted broadcast
|
||
|
* @throws IllegalArgumentException if name is non-null and its length is less than 4
|
||
|
* characters or greater than 16 characters
|
||
|
* @return this builder
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public Builder setBroadcastCode(@Nullable byte[] broadcastCode) {
|
||
|
if (broadcastCode != null
|
||
|
&& ((broadcastCode.length > 16) || (broadcastCode.length < 4))) {
|
||
|
throw new IllegalArgumentException("Invalid broadcast code length");
|
||
|
}
|
||
|
mBroadcastCode = broadcastCode;
|
||
|
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, 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 settings to the broadcast group.
|
||
|
*
|
||
|
* @param subgroupSettings contains subgroup's setting data
|
||
|
* @return this builder
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public Builder addSubgroupSettings(
|
||
|
@NonNull BluetoothLeBroadcastSubgroupSettings subgroupSettings) {
|
||
|
Objects.requireNonNull(subgroupSettings, "subgroupSettings cannot be null");
|
||
|
mSubgroupSettings.add(subgroupSettings);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear subgroup settings list so that one can reset the builder
|
||
|
*
|
||
|
* @return this builder
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public Builder clearSubgroupSettings() {
|
||
|
mSubgroupSettings.clear();
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build {@link BluetoothLeBroadcastSettings}.
|
||
|
*
|
||
|
* @return {@link BluetoothLeBroadcastSettings}
|
||
|
* @throws IllegalArgumentException if the object cannot be built
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@NonNull
|
||
|
public BluetoothLeBroadcastSettings build() {
|
||
|
if (mSubgroupSettings.isEmpty()) {
|
||
|
throw new IllegalArgumentException("Must contain at least one subgroup");
|
||
|
}
|
||
|
return new BluetoothLeBroadcastSettings(
|
||
|
mIsPublicBroadcast,
|
||
|
mBroadcastName,
|
||
|
mBroadcastCode,
|
||
|
mPublicBroadcastMetadata,
|
||
|
mSubgroupSettings);
|
||
|
}
|
||
|
}
|
||
|
}
|