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