• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.IntDef;
20 import android.annotation.NonNull;
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.Objects;
28 
29 /**
30  * Represents the codec configuration for a Bluetooth A2DP source device.
31  *
32  * {@see BluetoothA2dp}
33  *
34  * {@hide}
35  */
36 public final class BluetoothCodecConfig implements Parcelable {
37     // Add an entry for each source codec here.
38     // NOTE: The values should be same as those listed in the following file:
39     //   hardware/libhardware/include/hardware/bt_av.h
40 
41     /** @hide */
42     @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
43             SOURCE_CODEC_TYPE_SBC,
44             SOURCE_CODEC_TYPE_AAC,
45             SOURCE_CODEC_TYPE_APTX,
46             SOURCE_CODEC_TYPE_APTX_HD,
47             SOURCE_CODEC_TYPE_LDAC,
48             SOURCE_CODEC_TYPE_MAX,
49             SOURCE_CODEC_TYPE_INVALID
50     })
51     @Retention(RetentionPolicy.SOURCE)
52     public @interface SourceCodecType {}
53 
54     @UnsupportedAppUsage
55     public static final int SOURCE_CODEC_TYPE_SBC = 0;
56 
57     @UnsupportedAppUsage
58     public static final int SOURCE_CODEC_TYPE_AAC = 1;
59 
60     @UnsupportedAppUsage
61     public static final int SOURCE_CODEC_TYPE_APTX = 2;
62 
63     @UnsupportedAppUsage
64     public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
65 
66     @UnsupportedAppUsage
67     public static final int SOURCE_CODEC_TYPE_LDAC = 4;
68 
69     @UnsupportedAppUsage
70     public static final int SOURCE_CODEC_TYPE_MAX = 5;
71 
72     @UnsupportedAppUsage
73     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
74 
75     /** @hide */
76     @IntDef(prefix = "CODEC_PRIORITY_", value = {
77             CODEC_PRIORITY_DISABLED,
78             CODEC_PRIORITY_DEFAULT,
79             CODEC_PRIORITY_HIGHEST
80     })
81     @Retention(RetentionPolicy.SOURCE)
82     public @interface CodecPriority {}
83 
84     @UnsupportedAppUsage
85     public static final int CODEC_PRIORITY_DISABLED = -1;
86 
87     @UnsupportedAppUsage
88     public static final int CODEC_PRIORITY_DEFAULT = 0;
89 
90     @UnsupportedAppUsage
91     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
92 
93 
94     /** @hide */
95     @IntDef(prefix = "SAMPLE_RATE_", value = {
96             SAMPLE_RATE_NONE,
97             SAMPLE_RATE_44100,
98             SAMPLE_RATE_48000,
99             SAMPLE_RATE_88200,
100             SAMPLE_RATE_96000,
101             SAMPLE_RATE_176400,
102             SAMPLE_RATE_192000
103     })
104     @Retention(RetentionPolicy.SOURCE)
105     public @interface SampleRate {}
106 
107     @UnsupportedAppUsage
108     public static final int SAMPLE_RATE_NONE = 0;
109 
110     @UnsupportedAppUsage
111     public static final int SAMPLE_RATE_44100 = 0x1 << 0;
112 
113     @UnsupportedAppUsage
114     public static final int SAMPLE_RATE_48000 = 0x1 << 1;
115 
116     @UnsupportedAppUsage
117     public static final int SAMPLE_RATE_88200 = 0x1 << 2;
118 
119     @UnsupportedAppUsage
120     public static final int SAMPLE_RATE_96000 = 0x1 << 3;
121 
122     @UnsupportedAppUsage
123     public static final int SAMPLE_RATE_176400 = 0x1 << 4;
124 
125     @UnsupportedAppUsage
126     public static final int SAMPLE_RATE_192000 = 0x1 << 5;
127 
128 
129     /** @hide */
130     @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
131             BITS_PER_SAMPLE_NONE,
132             BITS_PER_SAMPLE_16,
133             BITS_PER_SAMPLE_24,
134             BITS_PER_SAMPLE_32
135     })
136     @Retention(RetentionPolicy.SOURCE)
137     public @interface BitsPerSample {}
138 
139     @UnsupportedAppUsage
140     public static final int BITS_PER_SAMPLE_NONE = 0;
141 
142     @UnsupportedAppUsage
143     public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
144 
145     @UnsupportedAppUsage
146     public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
147 
148     @UnsupportedAppUsage
149     public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
150 
151 
152     /** @hide */
153     @IntDef(prefix = "CHANNEL_MODE_", value = {
154             CHANNEL_MODE_NONE,
155             CHANNEL_MODE_MONO,
156             CHANNEL_MODE_STEREO
157     })
158     @Retention(RetentionPolicy.SOURCE)
159     public @interface ChannelMode {}
160 
161     @UnsupportedAppUsage
162     public static final int CHANNEL_MODE_NONE = 0;
163 
164     @UnsupportedAppUsage
165     public static final int CHANNEL_MODE_MONO = 0x1 << 0;
166 
167     @UnsupportedAppUsage
168     public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
169 
170     private final @SourceCodecType int mCodecType;
171     private @CodecPriority int mCodecPriority;
172     private final @SampleRate int mSampleRate;
173     private final @BitsPerSample int mBitsPerSample;
174     private final @ChannelMode int mChannelMode;
175     private final long mCodecSpecific1;
176     private final long mCodecSpecific2;
177     private final long mCodecSpecific3;
178     private final long mCodecSpecific4;
179 
180     @UnsupportedAppUsage
BluetoothCodecConfig(@ourceCodecType int codecType, @CodecPriority int codecPriority, @SampleRate int sampleRate, @BitsPerSample int bitsPerSample, @ChannelMode int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4)181     public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
182             @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
183             @ChannelMode int channelMode, long codecSpecific1,
184             long codecSpecific2, long codecSpecific3,
185             long codecSpecific4) {
186         mCodecType = codecType;
187         mCodecPriority = codecPriority;
188         mSampleRate = sampleRate;
189         mBitsPerSample = bitsPerSample;
190         mChannelMode = channelMode;
191         mCodecSpecific1 = codecSpecific1;
192         mCodecSpecific2 = codecSpecific2;
193         mCodecSpecific3 = codecSpecific3;
194         mCodecSpecific4 = codecSpecific4;
195     }
196 
197     @UnsupportedAppUsage
BluetoothCodecConfig(@ourceCodecType int codecType)198     public BluetoothCodecConfig(@SourceCodecType int codecType) {
199         mCodecType = codecType;
200         mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
201         mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
202         mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
203         mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
204         mCodecSpecific1 = 0;
205         mCodecSpecific2 = 0;
206         mCodecSpecific3 = 0;
207         mCodecSpecific4 = 0;
208     }
209 
210     @Override
equals(Object o)211     public boolean equals(Object o) {
212         if (o instanceof BluetoothCodecConfig) {
213             BluetoothCodecConfig other = (BluetoothCodecConfig) o;
214             return (other.mCodecType == mCodecType
215                     && other.mCodecPriority == mCodecPriority
216                     && other.mSampleRate == mSampleRate
217                     && other.mBitsPerSample == mBitsPerSample
218                     && other.mChannelMode == mChannelMode
219                     && other.mCodecSpecific1 == mCodecSpecific1
220                     && other.mCodecSpecific2 == mCodecSpecific2
221                     && other.mCodecSpecific3 == mCodecSpecific3
222                     && other.mCodecSpecific4 == mCodecSpecific4);
223         }
224         return false;
225     }
226 
227     /**
228      * Returns a hash based on the config values
229      *
230      * @return a hash based on the config values
231      * @hide
232      */
233     @Override
hashCode()234     public int hashCode() {
235         return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
236                 mBitsPerSample, mChannelMode, mCodecSpecific1,
237                 mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
238     }
239 
240     /**
241      * Checks whether the object contains valid codec configuration.
242      *
243      * @return true if the object contains valid codec configuration, otherwise false.
244      * @hide
245      */
isValid()246     public boolean isValid() {
247         return (mSampleRate != SAMPLE_RATE_NONE)
248                 && (mBitsPerSample != BITS_PER_SAMPLE_NONE)
249                 && (mChannelMode != CHANNEL_MODE_NONE);
250     }
251 
252     /**
253      * Adds capability string to an existing string.
254      *
255      * @param prevStr the previous string with the capabilities. Can be a null pointer.
256      * @param capStr the capability string to append to prevStr argument.
257      * @return the result string in the form "prevStr|capStr".
258      */
appendCapabilityToString(String prevStr, String capStr)259     private static String appendCapabilityToString(String prevStr,
260             String capStr) {
261         if (prevStr == null) {
262             return capStr;
263         }
264         return prevStr + "|" + capStr;
265     }
266 
267     @Override
toString()268     public String toString() {
269         String sampleRateStr = null;
270         if (mSampleRate == SAMPLE_RATE_NONE) {
271             sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
272         }
273         if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
274             sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
275         }
276         if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
277             sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
278         }
279         if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
280             sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
281         }
282         if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
283             sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
284         }
285         if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
286             sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
287         }
288         if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
289             sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
290         }
291 
292         String bitsPerSampleStr = null;
293         if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
294             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
295         }
296         if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
297             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
298         }
299         if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
300             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
301         }
302         if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
303             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
304         }
305 
306         String channelModeStr = null;
307         if (mChannelMode == CHANNEL_MODE_NONE) {
308             channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
309         }
310         if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
311             channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
312         }
313         if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
314             channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
315         }
316 
317         return "{codecName:" + getCodecName()
318                 + ",mCodecType:" + mCodecType
319                 + ",mCodecPriority:" + mCodecPriority
320                 + ",mSampleRate:" + String.format("0x%x", mSampleRate)
321                 + "(" + sampleRateStr + ")"
322                 + ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample)
323                 + "(" + bitsPerSampleStr + ")"
324                 + ",mChannelMode:" + String.format("0x%x", mChannelMode)
325                 + "(" + channelModeStr + ")"
326                 + ",mCodecSpecific1:" + mCodecSpecific1
327                 + ",mCodecSpecific2:" + mCodecSpecific2
328                 + ",mCodecSpecific3:" + mCodecSpecific3
329                 + ",mCodecSpecific4:" + mCodecSpecific4 + "}";
330     }
331 
332     /**
333      * Always returns 0
334      *
335      * @return 0
336      * @hide
337      */
338     @Override
describeContents()339     public int describeContents() {
340         return 0;
341     }
342 
343     public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecConfig> CREATOR =
344             new Parcelable.Creator<BluetoothCodecConfig>() {
345                 public BluetoothCodecConfig createFromParcel(Parcel in) {
346                     final int codecType = in.readInt();
347                     final int codecPriority = in.readInt();
348                     final int sampleRate = in.readInt();
349                     final int bitsPerSample = in.readInt();
350                     final int channelMode = in.readInt();
351                     final long codecSpecific1 = in.readLong();
352                     final long codecSpecific2 = in.readLong();
353                     final long codecSpecific3 = in.readLong();
354                     final long codecSpecific4 = in.readLong();
355                     return new BluetoothCodecConfig(codecType, codecPriority,
356                             sampleRate, bitsPerSample,
357                             channelMode, codecSpecific1,
358                             codecSpecific2, codecSpecific3,
359                             codecSpecific4);
360                 }
361 
362                 public BluetoothCodecConfig[] newArray(int size) {
363                     return new BluetoothCodecConfig[size];
364                 }
365             };
366 
367     /**
368      * Flattens the object to a parcel
369      *
370      * @param out The Parcel in which the object should be written.
371      * @param flags Additional flags about how the object should be written.
372      *
373      * @hide
374      */
375     @Override
writeToParcel(Parcel out, int flags)376     public void writeToParcel(Parcel out, int flags) {
377         out.writeInt(mCodecType);
378         out.writeInt(mCodecPriority);
379         out.writeInt(mSampleRate);
380         out.writeInt(mBitsPerSample);
381         out.writeInt(mChannelMode);
382         out.writeLong(mCodecSpecific1);
383         out.writeLong(mCodecSpecific2);
384         out.writeLong(mCodecSpecific3);
385         out.writeLong(mCodecSpecific4);
386     }
387 
388     /**
389      * Gets the codec name.
390      *
391      * @return the codec name
392      */
getCodecName()393     public @NonNull String getCodecName() {
394         switch (mCodecType) {
395             case SOURCE_CODEC_TYPE_SBC:
396                 return "SBC";
397             case SOURCE_CODEC_TYPE_AAC:
398                 return "AAC";
399             case SOURCE_CODEC_TYPE_APTX:
400                 return "aptX";
401             case SOURCE_CODEC_TYPE_APTX_HD:
402                 return "aptX HD";
403             case SOURCE_CODEC_TYPE_LDAC:
404                 return "LDAC";
405             case SOURCE_CODEC_TYPE_INVALID:
406                 return "INVALID CODEC";
407             default:
408                 break;
409         }
410         return "UNKNOWN CODEC(" + mCodecType + ")";
411     }
412 
413     /**
414      * Gets the codec type.
415      * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
416      *
417      * @return the codec type
418      */
419     @UnsupportedAppUsage
getCodecType()420     public @SourceCodecType int getCodecType() {
421         return mCodecType;
422     }
423 
424     /**
425      * Checks whether the codec is mandatory.
426      *
427      * @return true if the codec is mandatory, otherwise false.
428      */
isMandatoryCodec()429     public boolean isMandatoryCodec() {
430         return mCodecType == SOURCE_CODEC_TYPE_SBC;
431     }
432 
433     /**
434      * Gets the codec selection priority.
435      * The codec selection priority is relative to other codecs: larger value
436      * means higher priority. If 0, reset to default.
437      *
438      * @return the codec priority
439      */
440     @UnsupportedAppUsage
getCodecPriority()441     public @CodecPriority int getCodecPriority() {
442         return mCodecPriority;
443     }
444 
445     /**
446      * Sets the codec selection priority.
447      * The codec selection priority is relative to other codecs: larger value
448      * means higher priority. If 0, reset to default.
449      *
450      * @param codecPriority the codec priority
451      * @hide
452      */
453     @UnsupportedAppUsage
setCodecPriority(@odecPriority int codecPriority)454     public void setCodecPriority(@CodecPriority int codecPriority) {
455         mCodecPriority = codecPriority;
456     }
457 
458     /**
459      * Gets the codec sample rate. The value can be a bitmask with all
460      * supported sample rates:
461      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
462      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
463      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
464      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
465      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
466      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
467      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
468      *
469      * @return the codec sample rate
470      */
471     @UnsupportedAppUsage
getSampleRate()472     public @SampleRate int getSampleRate() {
473         return mSampleRate;
474     }
475 
476     /**
477      * Gets the codec bits per sample. The value can be a bitmask with all
478      * bits per sample supported:
479      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
480      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
481      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
482      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
483      *
484      * @return the codec bits per sample
485      */
486     @UnsupportedAppUsage
getBitsPerSample()487     public @BitsPerSample int getBitsPerSample() {
488         return mBitsPerSample;
489     }
490 
491     /**
492      * Gets the codec channel mode. The value can be a bitmask with all
493      * supported channel modes:
494      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
495      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
496      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
497      *
498      * @return the codec channel mode
499      * @hide
500      */
501     @UnsupportedAppUsage
getChannelMode()502     public @ChannelMode int getChannelMode() {
503         return mChannelMode;
504     }
505 
506     /**
507      * Gets a codec specific value1.
508      *
509      * @return a codec specific value1.
510      */
511     @UnsupportedAppUsage
getCodecSpecific1()512     public long getCodecSpecific1() {
513         return mCodecSpecific1;
514     }
515 
516     /**
517      * Gets a codec specific value2.
518      *
519      * @return a codec specific value2
520      * @hide
521      */
522     @UnsupportedAppUsage
getCodecSpecific2()523     public long getCodecSpecific2() {
524         return mCodecSpecific2;
525     }
526 
527     /**
528      * Gets a codec specific value3.
529      *
530      * @return a codec specific value3
531      * @hide
532      */
533     @UnsupportedAppUsage
getCodecSpecific3()534     public long getCodecSpecific3() {
535         return mCodecSpecific3;
536     }
537 
538     /**
539      * Gets a codec specific value4.
540      *
541      * @return a codec specific value4
542      * @hide
543      */
544     @UnsupportedAppUsage
getCodecSpecific4()545     public long getCodecSpecific4() {
546         return mCodecSpecific4;
547     }
548 
549     /**
550      * Checks whether a value set presented by a bitmask has zero or single bit
551      *
552      * @param valueSet the value set presented by a bitmask
553      * @return true if the valueSet contains zero or single bit, otherwise false.
554      * @hide
555      */
hasSingleBit(int valueSet)556     private static boolean hasSingleBit(int valueSet) {
557         return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
558     }
559 
560     /**
561      * Checks whether the object contains none or single sample rate.
562      *
563      * @return true if the object contains none or single sample rate, otherwise false.
564      * @hide
565      */
hasSingleSampleRate()566     public boolean hasSingleSampleRate() {
567         return hasSingleBit(mSampleRate);
568     }
569 
570     /**
571      * Checks whether the object contains none or single bits per sample.
572      *
573      * @return true if the object contains none or single bits per sample, otherwise false.
574      * @hide
575      */
hasSingleBitsPerSample()576     public boolean hasSingleBitsPerSample() {
577         return hasSingleBit(mBitsPerSample);
578     }
579 
580     /**
581      * Checks whether the object contains none or single channel mode.
582      *
583      * @return true if the object contains none or single channel mode, otherwise false.
584      * @hide
585      */
hasSingleChannelMode()586     public boolean hasSingleChannelMode() {
587         return hasSingleBit(mChannelMode);
588     }
589 
590     /**
591      * Checks whether the audio feeding parameters are same.
592      *
593      * @param other the codec config to compare against
594      * @return true if the audio feeding parameters are same, otherwise false
595      * @hide
596      */
sameAudioFeedingParameters(BluetoothCodecConfig other)597     public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
598         return (other != null && other.mSampleRate == mSampleRate
599                 && other.mBitsPerSample == mBitsPerSample
600                 && other.mChannelMode == mChannelMode);
601     }
602 
603     /**
604      * Checks whether another codec config has the similar feeding parameters.
605      * Any parameters with NONE value will be considered to be a wildcard matching.
606      *
607      * @param other the codec config to compare against
608      * @return true if the audio feeding parameters are similar, otherwise false.
609      * @hide
610      */
similarCodecFeedingParameters(BluetoothCodecConfig other)611     public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
612         if (other == null || mCodecType != other.mCodecType) {
613             return false;
614         }
615         int sampleRate = other.mSampleRate;
616         if (mSampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE
617                 || sampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE) {
618             sampleRate = mSampleRate;
619         }
620         int bitsPerSample = other.mBitsPerSample;
621         if (mBitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE
622                 || bitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
623             bitsPerSample = mBitsPerSample;
624         }
625         int channelMode = other.mChannelMode;
626         if (mChannelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE
627                 || channelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE) {
628             channelMode = mChannelMode;
629         }
630         return sameAudioFeedingParameters(new BluetoothCodecConfig(
631                 mCodecType, /* priority */ 0, sampleRate, bitsPerSample, channelMode,
632                 /* specific1 */ 0, /* specific2 */ 0, /* specific3 */ 0,
633                 /* specific4 */ 0));
634     }
635 
636     /**
637      * Checks whether the codec specific parameters are the same.
638      *
639      * @param other the codec config to compare against
640      * @return true if the codec specific parameters are the same, otherwise false.
641      * @hide
642      */
sameCodecSpecificParameters(BluetoothCodecConfig other)643     public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
644         if (other == null && mCodecType != other.mCodecType) {
645             return false;
646         }
647         // Currently we only care about the LDAC Playback Quality at CodecSpecific1
648         switch (mCodecType) {
649             case SOURCE_CODEC_TYPE_LDAC:
650                 if (mCodecSpecific1 != other.mCodecSpecific1) {
651                     return false;
652                 }
653                 // fall through
654             default:
655                 return true;
656         }
657     }
658 }
659