• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Objects;
27 
28 /**
29  * Represents the codec status (configuration and capability) for a Bluetooth
30  * Le Audio source device.
31  *
32  * {@see BluetoothLeAudio}
33  */
34 public final class BluetoothLeAudioCodecStatus implements Parcelable {
35     /**
36      * Extra for the codec configuration intents of the individual profiles.
37      *
38      * This extra represents the current codec status of the Le Audio
39      * profile.
40      */
41     public static final String EXTRA_LE_AUDIO_CODEC_STATUS =
42             "android.bluetooth.extra.LE_AUDIO_CODEC_STATUS";
43 
44     private final @Nullable BluetoothLeAudioCodecConfig mInputCodecConfig;
45     private final @Nullable BluetoothLeAudioCodecConfig mOutputCodecConfig;
46     private final @Nullable List<BluetoothLeAudioCodecConfig> mInputCodecsLocalCapabilities;
47     private final @Nullable List<BluetoothLeAudioCodecConfig> mOutputCodecsLocalCapabilities;
48     private final @Nullable List<BluetoothLeAudioCodecConfig> mInputCodecsSelectableCapabilities;
49     private final @Nullable List<BluetoothLeAudioCodecConfig> mOutputCodecsSelectableCapabilities;
50 
51     /**
52      * Represents the codec status for a Bluetooth LE Audio source device.
53      *
54      * @param inputCodecConfig the current input code configutration.
55      * @param outputCodecConfig the current output code configutration.
56      * @param inputCodecsLocalCapabilities the local input codecs capabilities.
57      * @param outputCodecsLocalCapabilities the local output codecs capabilities.
58      * @param inputCodecsSelectableCapabilities the selectable input codecs capabilities.
59      * @param outputCodecsSelectableCapabilities the selectable output codecs capabilities.
60      */
BluetoothLeAudioCodecStatus(@ullable BluetoothLeAudioCodecConfig inputCodecConfig, @Nullable BluetoothLeAudioCodecConfig outputCodecConfig, @NonNull List<BluetoothLeAudioCodecConfig> inputCodecsLocalCapabilities, @NonNull List<BluetoothLeAudioCodecConfig> outputCodecsLocalCapabilities, @NonNull List<BluetoothLeAudioCodecConfig> inputCodecsSelectableCapabilities, @NonNull List<BluetoothLeAudioCodecConfig> outputCodecsSelectableCapabilities)61     public BluetoothLeAudioCodecStatus(@Nullable BluetoothLeAudioCodecConfig inputCodecConfig,
62             @Nullable BluetoothLeAudioCodecConfig outputCodecConfig,
63             @NonNull List<BluetoothLeAudioCodecConfig> inputCodecsLocalCapabilities,
64             @NonNull List<BluetoothLeAudioCodecConfig> outputCodecsLocalCapabilities,
65             @NonNull List<BluetoothLeAudioCodecConfig> inputCodecsSelectableCapabilities,
66             @NonNull List<BluetoothLeAudioCodecConfig> outputCodecsSelectableCapabilities) {
67         mInputCodecConfig = inputCodecConfig;
68         mOutputCodecConfig = outputCodecConfig;
69         mInputCodecsLocalCapabilities = inputCodecsLocalCapabilities;
70         mOutputCodecsLocalCapabilities = outputCodecsLocalCapabilities;
71         mInputCodecsSelectableCapabilities = inputCodecsSelectableCapabilities;
72         mOutputCodecsSelectableCapabilities = outputCodecsSelectableCapabilities;
73     }
74 
BluetoothLeAudioCodecStatus(Parcel in)75     private BluetoothLeAudioCodecStatus(Parcel in) {
76         mInputCodecConfig = in.readTypedObject(BluetoothLeAudioCodecConfig.CREATOR);
77         mOutputCodecConfig = in.readTypedObject(BluetoothLeAudioCodecConfig.CREATOR);
78         mInputCodecsLocalCapabilities =
79                     in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR);
80         mOutputCodecsLocalCapabilities =
81                     in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR);
82         mInputCodecsSelectableCapabilities =
83                 in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR);
84         mOutputCodecsSelectableCapabilities =
85                 in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR);
86     }
87 
88     @Override
equals(@ullable Object o)89     public boolean equals(@Nullable Object o) {
90         if (o instanceof BluetoothLeAudioCodecStatus) {
91             BluetoothLeAudioCodecStatus other = (BluetoothLeAudioCodecStatus) o;
92             return (Objects.equals(other.mInputCodecConfig, mInputCodecConfig)
93                     && Objects.equals(other.mOutputCodecConfig, mOutputCodecConfig)
94                     && sameCapabilities(other.mInputCodecsLocalCapabilities,
95                                             mInputCodecsLocalCapabilities)
96                     && sameCapabilities(other.mOutputCodecsLocalCapabilities,
97                                             mOutputCodecsLocalCapabilities)
98                     && sameCapabilities(other.mInputCodecsSelectableCapabilities,
99                     mInputCodecsSelectableCapabilities)
100                     && sameCapabilities(other.mOutputCodecsSelectableCapabilities,
101                     mOutputCodecsSelectableCapabilities));
102         }
103         return false;
104     }
105 
106     /**
107      * Checks whether two lists of capabilities contain same capabilities.
108      * The order of the capabilities in each list is ignored.
109      *
110      * @param c1 the first list of capabilities to compare
111      * @param c2 the second list of capabilities to compare
112      * @return {@code true} if both lists contain same capabilities
113      */
sameCapabilities(@ullable List<BluetoothLeAudioCodecConfig> c1, @Nullable List<BluetoothLeAudioCodecConfig> c2)114     private static boolean sameCapabilities(@Nullable List<BluetoothLeAudioCodecConfig> c1,
115                                            @Nullable List<BluetoothLeAudioCodecConfig> c2) {
116         if (c1 == null) {
117             return (c2 == null);
118         }
119         if (c2 == null) {
120             return false;
121         }
122         if (c1.size() != c2.size()) {
123             return false;
124         }
125         return c1.containsAll(c2);
126     }
127 
isCodecConfigSelectable(BluetoothLeAudioCodecConfig codecConfig, BluetoothLeAudioCodecConfig selectableConfig)128     private boolean isCodecConfigSelectable(BluetoothLeAudioCodecConfig codecConfig,
129                 BluetoothLeAudioCodecConfig selectableConfig) {
130         if (codecConfig.getCodecType() != selectableConfig.getCodecType()) {
131             return false;
132         }
133         if ((codecConfig.getFrameDuration() != BluetoothLeAudioCodecConfig.FRAME_DURATION_NONE)
134                 && ((codecConfig.getFrameDuration() & selectableConfig.getFrameDuration()) == 0)) {
135             return false;
136         }
137         if ((codecConfig.getChannelCount() != BluetoothLeAudioCodecConfig.CHANNEL_COUNT_NONE)
138                 && ((codecConfig.getChannelCount() & selectableConfig.getChannelCount()) == 0)) {
139             return false;
140         }
141         if ((codecConfig.getSampleRate() != BluetoothLeAudioCodecConfig.SAMPLE_RATE_NONE)
142                 && ((codecConfig.getSampleRate() & selectableConfig.getSampleRate()) == 0)) {
143             return false;
144         }
145         if ((codecConfig.getBitsPerSample() != BluetoothLeAudioCodecConfig.BITS_PER_SAMPLE_NONE)
146                 && ((codecConfig.getBitsPerSample() & selectableConfig.getBitsPerSample()) == 0)) {
147             return false;
148         }
149         if ((codecConfig.getOctetsPerFrame() != 0)
150                 && ((codecConfig.getOctetsPerFrame() < selectableConfig.getMinOctetsPerFrame())
151                 || (codecConfig.getOctetsPerFrame() > selectableConfig.getMaxOctetsPerFrame()))) {
152             return false;
153         }
154         return true;
155     }
156     /**
157      * Checks whether the Input codec config matches the selectable capabilities.
158      * Any parameters of the codec config with NONE value will be considered a wildcard matching.
159      *
160      * @param codecConfig the codec config to compare against
161      * @return {@code true} if the codec config matches, {@code false} otherwise
162      */
isInputCodecConfigSelectable(@ullable BluetoothLeAudioCodecConfig codecConfig)163     public boolean isInputCodecConfigSelectable(@Nullable BluetoothLeAudioCodecConfig codecConfig) {
164         if (codecConfig == null) {
165             return false;
166         }
167         for (BluetoothLeAudioCodecConfig selectableConfig : mInputCodecsSelectableCapabilities) {
168             if (isCodecConfigSelectable(codecConfig, selectableConfig)) {
169                 return true;
170             }
171         }
172         return false;
173     }
174 
175     /**
176      * Checks whether the Output codec config matches the selectable capabilities.
177      * Any parameters of the codec config with NONE value will be considered a wildcard matching.
178      *
179      * @param codecConfig the codec config to compare against
180      * @return {@code true} if the codec config matches, {@code false} otherwise
181      */
isOutputCodecConfigSelectable( @ullable BluetoothLeAudioCodecConfig codecConfig)182     public boolean isOutputCodecConfigSelectable(
183                 @Nullable BluetoothLeAudioCodecConfig codecConfig) {
184         if (codecConfig == null) {
185             return false;
186         }
187         for (BluetoothLeAudioCodecConfig selectableConfig : mOutputCodecsSelectableCapabilities) {
188             if (isCodecConfigSelectable(codecConfig, selectableConfig)) {
189                 return true;
190             }
191         }
192         return false;
193     }
194 
195     /**
196      * Returns a hash based on the codec config and local capabilities.
197      */
198     @Override
hashCode()199     public int hashCode() {
200         return Objects.hash(mInputCodecConfig, mOutputCodecConfig,
201                         mInputCodecsLocalCapabilities, mOutputCodecsLocalCapabilities,
202                         mInputCodecsSelectableCapabilities, mOutputCodecsSelectableCapabilities);
203     }
204 
205     /**
206      * Returns a {@link String} that describes each BluetoothLeAudioCodecStatus parameter
207      * current value.
208      */
209     @Override
toString()210     public String toString() {
211         return "{mInputCodecConfig:" + mInputCodecConfig
212                 + ",mOutputCodecConfig:" + mOutputCodecConfig
213                 + ",mInputCodecsLocalCapabilities:" + mInputCodecsLocalCapabilities
214                 + ",mOutputCodecsLocalCapabilities:" + mOutputCodecsLocalCapabilities
215                 + ",mInputCodecsSelectableCapabilities:" + mInputCodecsSelectableCapabilities
216                 + ",mOutputCodecsSelectableCapabilities:" + mOutputCodecsSelectableCapabilities
217                 + "}";
218     }
219 
220     /**
221      * @return 0
222      */
223     @Override
describeContents()224     public int describeContents() {
225         return 0;
226     }
227 
228     /**
229      * {@link Parcelable.Creator} interface implementation.
230      */
231     public static final @android.annotation.NonNull
232             Parcelable.Creator<BluetoothLeAudioCodecStatus> CREATOR =
233             new Parcelable.Creator<BluetoothLeAudioCodecStatus>() {
234                 public BluetoothLeAudioCodecStatus createFromParcel(Parcel in) {
235                     return new BluetoothLeAudioCodecStatus(in);
236                 }
237 
238                 public BluetoothLeAudioCodecStatus[] newArray(int size) {
239                     return new BluetoothLeAudioCodecStatus[size];
240                 }
241             };
242 
243     /**
244      * Flattens the object to a parcel.
245      *
246      * @param out The Parcel in which the object should be written
247      * @param flags Additional flags about how the object should be written
248      */
249     @Override
writeToParcel(@onNull Parcel out, int flags)250     public void writeToParcel(@NonNull Parcel out, int flags) {
251         out.writeTypedObject(mInputCodecConfig, flags);
252         out.writeTypedObject(mOutputCodecConfig, flags);
253         out.writeTypedList(mInputCodecsLocalCapabilities);
254         out.writeTypedList(mOutputCodecsLocalCapabilities);
255         out.writeTypedList(mInputCodecsSelectableCapabilities);
256         out.writeTypedList(mOutputCodecsSelectableCapabilities);
257     }
258 
259     /**
260      * Returns the current Input codec configuration.
261      *
262      * @return The current input codec config.
263      */
getInputCodecConfig()264     public @Nullable BluetoothLeAudioCodecConfig getInputCodecConfig() {
265         return mInputCodecConfig;
266     }
267 
268     /**
269      * Returns the current Output codec configuration.
270      *
271      * @return The current output codec config.
272      */
getOutputCodecConfig()273     public @Nullable BluetoothLeAudioCodecConfig getOutputCodecConfig() {
274         return mOutputCodecConfig;
275     }
276 
277     /**
278      * Returns the input codecs local capabilities.
279      *
280      * @return The list of codec config that supported by the local system.
281      */
getInputCodecLocalCapabilities()282     public @NonNull List<BluetoothLeAudioCodecConfig> getInputCodecLocalCapabilities() {
283         return (mInputCodecsLocalCapabilities == null)
284                 ? Collections.emptyList() : mInputCodecsLocalCapabilities;
285     }
286 
287     /**
288      * Returns the output codecs local capabilities.
289      *
290      * @return The list of codec config that supported by the local system.
291      */
getOutputCodecLocalCapabilities()292     public @NonNull List<BluetoothLeAudioCodecConfig> getOutputCodecLocalCapabilities() {
293         return (mOutputCodecsLocalCapabilities == null)
294                 ? Collections.emptyList() : mOutputCodecsLocalCapabilities;
295     }
296 
297     /**
298      * Returns the Input codecs selectable capabilities.
299      *
300      * @return The list of codec config that supported by both of the local system and
301      * remote devices.
302      */
getInputCodecSelectableCapabilities()303     public @NonNull List<BluetoothLeAudioCodecConfig> getInputCodecSelectableCapabilities() {
304         return (mInputCodecsSelectableCapabilities == null)
305                 ? Collections.emptyList() : mInputCodecsSelectableCapabilities;
306     }
307 
308     /**
309      * Returns the Output codecs selectable capabilities.
310      *
311      * @return The list of codec config that supported by both of the local system and
312      * remote devices.
313      */
getOutputCodecSelectableCapabilities()314     public @NonNull List<BluetoothLeAudioCodecConfig> getOutputCodecSelectableCapabilities() {
315         return (mOutputCodecsSelectableCapabilities == null)
316                 ? Collections.emptyList() : mOutputCodecsSelectableCapabilities;
317     }
318 }
319