1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at: 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.bluetooth; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SystemApi; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import java.util.Objects; 28 29 /** 30 * This class contains the Broadcast Isochronous Channel level information as defined in the BASE 31 * structure of the Basic Audio Profile. 32 * 33 * @hide 34 */ 35 @SystemApi 36 public final class BluetoothLeBroadcastChannel implements Parcelable { 37 private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; 38 39 private final boolean mIsSelected; 40 private final int mChannelIndex; 41 private final BluetoothLeAudioCodecConfigMetadata mCodecMetadata; 42 BluetoothLeBroadcastChannel( boolean isSelected, int channelIndex, BluetoothLeAudioCodecConfigMetadata codecMetadata)43 private BluetoothLeBroadcastChannel( 44 boolean isSelected, 45 int channelIndex, 46 BluetoothLeAudioCodecConfigMetadata codecMetadata) { 47 mIsSelected = isSelected; 48 mChannelIndex = channelIndex; 49 mCodecMetadata = codecMetadata; 50 } 51 52 @Override equals(@ullable Object o)53 public boolean equals(@Nullable Object o) { 54 if (!(o instanceof BluetoothLeBroadcastChannel)) { 55 return false; 56 } 57 final BluetoothLeBroadcastChannel other = (BluetoothLeBroadcastChannel) o; 58 return mIsSelected == other.isSelected() 59 && mChannelIndex == other.getChannelIndex() 60 && mCodecMetadata.equals(other.getCodecMetadata()); 61 } 62 63 @Override hashCode()64 public int hashCode() { 65 return Objects.hash(mIsSelected, mChannelIndex, mCodecMetadata); 66 } 67 68 @Override toString()69 public String toString() { 70 return "BluetoothLeBroadcastChannel{" 71 + ("isSelected=" + mIsSelected) 72 + (", channelIndex=" + mChannelIndex) 73 + (", codecMetadata=" + mCodecMetadata) 74 + '}'; 75 } 76 77 /** 78 * Return true if the channel is selected by Broadcast Assistant for the Broadcast Sink. 79 * 80 * <p>Used by Broadcast Assistant and Sink, but not Broadcast Source 81 * 82 * @return true if the channel is selected by Broadcast Assistant for the Broadcast Sink 83 * @hide 84 */ 85 @SystemApi isSelected()86 public boolean isSelected() { 87 return mIsSelected; 88 } 89 90 /** 91 * Get the Broadcast Isochronous Channel index of this Broadcast Channel. 92 * 93 * @return Broadcast Isochronous Channel index 94 * @hide 95 */ 96 @SystemApi getChannelIndex()97 public int getChannelIndex() { 98 return mChannelIndex; 99 } 100 101 /** 102 * Return the codec specific configuration for this Broadcast Channel. 103 * 104 * @return codec specific configuration for this Broadcast Channel 105 * @hide 106 */ 107 @SystemApi getCodecMetadata()108 public @NonNull BluetoothLeAudioCodecConfigMetadata getCodecMetadata() { 109 return mCodecMetadata; 110 } 111 112 /** 113 * {@inheritDoc} 114 * 115 * @hide 116 */ 117 @Override describeContents()118 public int describeContents() { 119 return 0; 120 } 121 122 /** 123 * {@inheritDoc} 124 * 125 * @hide 126 */ 127 @Override writeToParcel(Parcel out, int flags)128 public void writeToParcel(Parcel out, int flags) { 129 out.writeBoolean(mIsSelected); 130 out.writeInt(mChannelIndex); 131 out.writeTypedObject(mCodecMetadata, 0); 132 } 133 134 /** 135 * A {@link Parcelable.Creator} to create {@link BluetoothLeBroadcastChannel} from parcel. 136 * 137 * @hide 138 */ 139 @SystemApi @NonNull 140 public static final Creator<BluetoothLeBroadcastChannel> CREATOR = 141 new Creator<>() { 142 public @NonNull BluetoothLeBroadcastChannel createFromParcel(@NonNull Parcel in) { 143 BluetoothLeBroadcastChannel.Builder builder = 144 new BluetoothLeBroadcastChannel.Builder(); 145 builder.setSelected(in.readBoolean()); 146 builder.setChannelIndex(in.readInt()); 147 builder.setCodecMetadata( 148 in.readTypedObject(BluetoothLeAudioCodecConfigMetadata.CREATOR)); 149 return builder.build(); 150 } 151 152 public @NonNull BluetoothLeBroadcastChannel[] newArray(int size) { 153 return new BluetoothLeBroadcastChannel[size]; 154 } 155 }; 156 157 /** 158 * Builder for {@link BluetoothLeBroadcastChannel}. 159 * 160 * @hide 161 */ 162 @SystemApi 163 public static final class Builder { 164 private boolean mIsSelected = false; 165 private int mChannelIndex = UNKNOWN_VALUE_PLACEHOLDER; 166 private BluetoothLeAudioCodecConfigMetadata mCodecMetadata = null; 167 168 /** 169 * Create an empty builder. 170 * 171 * @hide 172 */ 173 @SystemApi Builder()174 public Builder() {} 175 176 /** 177 * Create a builder with copies of information from original object. 178 * 179 * @param original original object 180 * @hide 181 */ 182 @SystemApi Builder(@onNull BluetoothLeBroadcastChannel original)183 public Builder(@NonNull BluetoothLeBroadcastChannel original) { 184 mIsSelected = original.isSelected(); 185 mChannelIndex = original.getChannelIndex(); 186 mCodecMetadata = original.getCodecMetadata(); 187 } 188 189 /** 190 * Set if the channel is selected by Broadcast Assistant for the Broadcast Sink. 191 * 192 * <p>Used by Broadcast Assistant and Sink, but not Broadcast Source 193 * 194 * @param isSelected true if the channel is selected by Broadcast Assistant for the 195 * Broadcast Sink 196 * @return this builder 197 * @hide 198 */ 199 @SystemApi setSelected(boolean isSelected)200 public @NonNull Builder setSelected(boolean isSelected) { 201 mIsSelected = isSelected; 202 return this; 203 } 204 205 /** 206 * Set the Broadcast Isochronous Channel index of this Broadcast Channel. 207 * 208 * @param channelIndex Broadcast Isochronous Channel index 209 * @throws IllegalArgumentException if the input argument is not valid 210 * @return this builder 211 * @hide 212 */ 213 @SystemApi setChannelIndex(int channelIndex)214 public @NonNull Builder setChannelIndex(int channelIndex) { 215 if (channelIndex == UNKNOWN_VALUE_PLACEHOLDER) { 216 throw new IllegalArgumentException( 217 "channelIndex cannot be " + UNKNOWN_VALUE_PLACEHOLDER); 218 } 219 mChannelIndex = channelIndex; 220 return this; 221 } 222 223 /** 224 * Set the codec specific configuration for this Broadcast Channel. 225 * 226 * @param codecMetadata codec specific configuration for this Broadcast Channel 227 * @throws NullPointerException if codecMetadata is null 228 * @return this builder 229 * @hide 230 */ 231 @SystemApi 232 @NonNull setCodecMetadata( @onNull BluetoothLeAudioCodecConfigMetadata codecMetadata)233 public Builder setCodecMetadata( 234 @NonNull BluetoothLeAudioCodecConfigMetadata codecMetadata) { 235 requireNonNull(codecMetadata); 236 mCodecMetadata = codecMetadata; 237 return this; 238 } 239 240 /** 241 * Build {@link BluetoothLeBroadcastChannel}. 242 * 243 * @return constructed {@link BluetoothLeBroadcastChannel} 244 * @throws NullPointerException if {@link NonNull} items are null 245 * @throws IllegalArgumentException if the object cannot be built 246 * @hide 247 */ 248 @SystemApi build()249 public @NonNull BluetoothLeBroadcastChannel build() { 250 requireNonNull(mCodecMetadata); 251 if (mChannelIndex == UNKNOWN_VALUE_PLACEHOLDER) { 252 throw new IllegalArgumentException( 253 "mChannelIndex cannot be " + UNKNOWN_VALUE_PLACEHOLDER); 254 } 255 return new BluetoothLeBroadcastChannel(mIsSelected, mChannelIndex, mCodecMetadata); 256 } 257 } 258 } 259