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