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.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SuppressLint;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import com.android.bluetooth.flags.Flags;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.Objects;
33 
34 /**
35  * Represents the codec configuration for a Bluetooth A2DP source device.
36  *
37  * <p>Contains the source codec type, the codec priority, the codec sample rate, the codec bits per
38  * sample, and the codec channel mode.
39  *
40  * <p>The source codec type values are the same as those supported by the device hardware.
41  *
42  * @see BluetoothA2dp
43  */
44 public final class BluetoothCodecConfig implements Parcelable {
45     /** @hide */
46     @IntDef(
47             prefix = "SOURCE_CODEC_TYPE_",
48             value = {
49                 SOURCE_CODEC_TYPE_SBC,
50                 SOURCE_CODEC_TYPE_AAC,
51                 SOURCE_CODEC_TYPE_APTX,
52                 SOURCE_CODEC_TYPE_APTX_HD,
53                 SOURCE_CODEC_TYPE_LDAC,
54                 SOURCE_CODEC_TYPE_LC3,
55                 SOURCE_CODEC_TYPE_OPUS,
56                 SOURCE_CODEC_TYPE_INVALID
57             })
58     @Retention(RetentionPolicy.SOURCE)
59     public @interface SourceCodecType {}
60 
61     /**
62      * Source codec type SBC. This is the mandatory source codec type.
63      *
64      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
65      *     BluetoothA2dp#getSupportedCodecTypes} instead.
66      */
67     @Deprecated public static final int SOURCE_CODEC_TYPE_SBC = 0;
68 
69     /**
70      * Source codec type AAC.
71      *
72      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
73      *     BluetoothA2dp#getSupportedCodecTypes} instead.
74      */
75     @Deprecated public static final int SOURCE_CODEC_TYPE_AAC = 1;
76 
77     /**
78      * Source codec type APTX.
79      *
80      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
81      *     BluetoothA2dp#getSupportedCodecTypes} instead.
82      */
83     @Deprecated public static final int SOURCE_CODEC_TYPE_APTX = 2;
84 
85     /**
86      * Source codec type APTX HD.
87      *
88      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
89      *     BluetoothA2dp#getSupportedCodecTypes} instead.
90      */
91     @Deprecated public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
92 
93     /**
94      * Source codec type LDAC.
95      *
96      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
97      *     BluetoothA2dp#getSupportedCodecTypes} instead.
98      */
99     @Deprecated public static final int SOURCE_CODEC_TYPE_LDAC = 4;
100 
101     /**
102      * Source codec type LC3.
103      *
104      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
105      *     BluetoothA2dp#getSupportedCodecTypes} instead.
106      */
107     @Deprecated public static final int SOURCE_CODEC_TYPE_LC3 = 5;
108 
109     /**
110      * Source codec type Opus.
111      *
112      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
113      *     BluetoothA2dp#getSupportedCodecTypes} instead.
114      */
115     @Deprecated public static final int SOURCE_CODEC_TYPE_OPUS = 6;
116 
117     /**
118      * Source codec type invalid. This is the default value used for codec type.
119      *
120      * @deprecated Use the {@link BluetoothCodecType} values returned by {@link
121      *     BluetoothA2dp#getSupportedCodecTypes} instead.
122      */
123     @Deprecated public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
124 
125     /** Represents the count of valid source codec types. */
126     static final int SOURCE_CODEC_TYPE_MAX = 7;
127 
128     /** @hide */
129     @IntDef(
130             prefix = "CODEC_PRIORITY_",
131             value = {CODEC_PRIORITY_DISABLED, CODEC_PRIORITY_DEFAULT, CODEC_PRIORITY_HIGHEST})
132     @Retention(RetentionPolicy.SOURCE)
133     public @interface CodecPriority {}
134 
135     /**
136      * Codec priority disabled. Used to indicate that this codec is disabled and should not be used.
137      */
138     public static final int CODEC_PRIORITY_DISABLED = -1;
139 
140     /** Codec priority default. Default value used for codec priority. */
141     public static final int CODEC_PRIORITY_DEFAULT = 0;
142 
143     /** Codec priority highest. Used to indicate the highest priority a codec can have. */
144     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
145 
146     /** @hide */
147     @IntDef(
148             prefix = "SAMPLE_RATE_",
149             value = {
150                 SAMPLE_RATE_NONE,
151                 SAMPLE_RATE_44100,
152                 SAMPLE_RATE_48000,
153                 SAMPLE_RATE_88200,
154                 SAMPLE_RATE_96000,
155                 SAMPLE_RATE_176400,
156                 SAMPLE_RATE_192000
157             })
158     @Retention(RetentionPolicy.SOURCE)
159     public @interface SampleRate {}
160 
161     /** Codec sample rate 0 Hz. Default value used for codec sample rate. */
162     public static final int SAMPLE_RATE_NONE = 0;
163 
164     /** Codec sample rate 44100 Hz. */
165     public static final int SAMPLE_RATE_44100 = 0x1 << 0;
166 
167     /** Codec sample rate 48000 Hz. */
168     public static final int SAMPLE_RATE_48000 = 0x1 << 1;
169 
170     /** Codec sample rate 88200 Hz. */
171     public static final int SAMPLE_RATE_88200 = 0x1 << 2;
172 
173     /** Codec sample rate 96000 Hz. */
174     public static final int SAMPLE_RATE_96000 = 0x1 << 3;
175 
176     /** Codec sample rate 176400 Hz. */
177     public static final int SAMPLE_RATE_176400 = 0x1 << 4;
178 
179     /** Codec sample rate 192000 Hz. */
180     public static final int SAMPLE_RATE_192000 = 0x1 << 5;
181 
182     /** @hide */
183     @IntDef(
184             prefix = "BITS_PER_SAMPLE_",
185             value = {
186                 BITS_PER_SAMPLE_NONE,
187                 BITS_PER_SAMPLE_16,
188                 BITS_PER_SAMPLE_24,
189                 BITS_PER_SAMPLE_32
190             })
191     @Retention(RetentionPolicy.SOURCE)
192     public @interface BitsPerSample {}
193 
194     /** Codec bits per sample 0. Default value of the codec bits per sample. */
195     public static final int BITS_PER_SAMPLE_NONE = 0;
196 
197     /** Codec bits per sample 16. */
198     public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
199 
200     /** Codec bits per sample 24. */
201     public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
202 
203     /** Codec bits per sample 32. */
204     public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
205 
206     /** @hide */
207     @IntDef(
208             prefix = "CHANNEL_MODE_",
209             value = {CHANNEL_MODE_NONE, CHANNEL_MODE_MONO, CHANNEL_MODE_STEREO})
210     @Retention(RetentionPolicy.SOURCE)
211     public @interface ChannelMode {}
212 
213     /** Codec channel mode NONE. Default value of the codec channel mode. */
214     public static final int CHANNEL_MODE_NONE = 0;
215 
216     /** Codec channel mode MONO. */
217     public static final int CHANNEL_MODE_MONO = 0x1 << 0;
218 
219     /** Codec channel mode STEREO. */
220     public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
221 
222     private final @Nullable BluetoothCodecType mCodecType;
223     private @CodecPriority int mCodecPriority;
224     private final @SampleRate int mSampleRate;
225     private final @BitsPerSample int mBitsPerSample;
226     private final @ChannelMode int mChannelMode;
227     private final long mCodecSpecific1;
228     private final long mCodecSpecific2;
229     private final long mCodecSpecific3;
230     private final long mCodecSpecific4;
231 
232     /**
233      * Creates a new BluetoothCodecConfig.
234      *
235      * @param codecType the source codec type
236      * @param codecPriority the priority of this codec
237      * @param sampleRate the codec sample rate
238      * @param bitsPerSample the bits per sample of this codec
239      * @param channelMode the channel mode of this codec
240      * @param codecSpecific1 the specific value 1
241      * @param codecSpecific2 the specific value 2
242      * @param codecSpecific3 the specific value 3
243      * @param codecSpecific4 the specific value 4 values to 0.
244      * @hide
245      */
246     @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)247     public BluetoothCodecConfig(
248             @SourceCodecType int codecType,
249             @CodecPriority int codecPriority,
250             @SampleRate int sampleRate,
251             @BitsPerSample int bitsPerSample,
252             @ChannelMode int channelMode,
253             long codecSpecific1,
254             long codecSpecific2,
255             long codecSpecific3,
256             long codecSpecific4) {
257         this(
258                 BluetoothCodecType.createFromType(codecType),
259                 codecPriority,
260                 sampleRate,
261                 bitsPerSample,
262                 channelMode,
263                 codecSpecific1,
264                 codecSpecific2,
265                 codecSpecific3,
266                 codecSpecific4);
267     }
268 
269     /**
270      * Creates a new BluetoothCodecConfig.
271      *
272      * @param codecType the source codec type
273      * @param codecPriority the priority of this codec
274      * @param sampleRate the codec sample rate
275      * @param bitsPerSample the bits per sample of this codec
276      * @param channelMode the channel mode of this codec
277      * @param codecSpecific1 the specific value 1
278      * @param codecSpecific2 the specific value 2
279      * @param codecSpecific3 the specific value 3
280      * @param codecSpecific4 the specific value 4 values to 0.
281      * @hide
282      */
BluetoothCodecConfig( @ullable BluetoothCodecType codecType, @CodecPriority int codecPriority, @SampleRate int sampleRate, @BitsPerSample int bitsPerSample, @ChannelMode int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4)283     public BluetoothCodecConfig(
284             @Nullable BluetoothCodecType codecType,
285             @CodecPriority int codecPriority,
286             @SampleRate int sampleRate,
287             @BitsPerSample int bitsPerSample,
288             @ChannelMode int channelMode,
289             long codecSpecific1,
290             long codecSpecific2,
291             long codecSpecific3,
292             long codecSpecific4) {
293         mCodecType = codecType;
294         mCodecPriority = codecPriority;
295         mSampleRate = sampleRate;
296         mBitsPerSample = bitsPerSample;
297         mChannelMode = channelMode;
298         mCodecSpecific1 = codecSpecific1;
299         mCodecSpecific2 = codecSpecific2;
300         mCodecSpecific3 = codecSpecific3;
301         mCodecSpecific4 = codecSpecific4;
302     }
303 
304     /**
305      * Creates a new BluetoothCodecConfig.
306      *
307      * <p>By default, the codec priority will be set to {@link
308      * BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to {@link
309      * BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to {@link
310      * BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to {@link
311      * BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific values to 0.
312      *
313      * @param codecType the source codec type
314      * @hide
315      */
BluetoothCodecConfig(@ourceCodecType int codecType)316     public BluetoothCodecConfig(@SourceCodecType int codecType) {
317         this(
318                 BluetoothCodecType.createFromType(codecType),
319                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
320                 BluetoothCodecConfig.SAMPLE_RATE_NONE,
321                 BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
322                 BluetoothCodecConfig.CHANNEL_MODE_NONE,
323                 0,
324                 0,
325                 0,
326                 0);
327     }
328 
BluetoothCodecConfig(Parcel in)329     private BluetoothCodecConfig(Parcel in) {
330         mCodecType = BluetoothCodecType.createFromType(in.readInt());
331         mCodecPriority = in.readInt();
332         mSampleRate = in.readInt();
333         mBitsPerSample = in.readInt();
334         mChannelMode = in.readInt();
335         mCodecSpecific1 = in.readLong();
336         mCodecSpecific2 = in.readLong();
337         mCodecSpecific3 = in.readLong();
338         mCodecSpecific4 = in.readLong();
339     }
340 
341     @Override
equals(@ullable Object o)342     public boolean equals(@Nullable Object o) {
343         if (o instanceof BluetoothCodecConfig) {
344             BluetoothCodecConfig other = (BluetoothCodecConfig) o;
345             return (Objects.equals(other.mCodecType, mCodecType)
346                     && other.mCodecPriority == mCodecPriority
347                     && other.mSampleRate == mSampleRate
348                     && other.mBitsPerSample == mBitsPerSample
349                     && other.mChannelMode == mChannelMode
350                     && other.mCodecSpecific1 == mCodecSpecific1
351                     && other.mCodecSpecific2 == mCodecSpecific2
352                     && other.mCodecSpecific3 == mCodecSpecific3
353                     && other.mCodecSpecific4 == mCodecSpecific4);
354         }
355         return false;
356     }
357 
358     /**
359      * Returns a hash representation of this BluetoothCodecConfig based on all the config values.
360      */
361     @Override
hashCode()362     public int hashCode() {
363         return Objects.hash(
364                 mCodecType,
365                 mCodecPriority,
366                 mSampleRate,
367                 mBitsPerSample,
368                 mChannelMode,
369                 mCodecSpecific1,
370                 mCodecSpecific2,
371                 mCodecSpecific3,
372                 mCodecSpecific4);
373     }
374 
375     /**
376      * Adds capability string to an existing string.
377      *
378      * @param prevStr the previous string with the capabilities. Can be a {@code null} pointer
379      * @param capStr the capability string to append to prevStr argument
380      * @return the result string in the form "prevStr|capStr"
381      */
appendCapabilityToString( @ullable String prevStr, @NonNull String capStr)382     private static String appendCapabilityToString(
383             @Nullable String prevStr, @NonNull String capStr) {
384         if (prevStr == null) {
385             return capStr;
386         }
387         return prevStr + "|" + capStr;
388     }
389 
390     /**
391      * Returns a {@link String} that describes each BluetoothCodecConfig parameter current value.
392      */
393     @Override
toString()394     public String toString() {
395         String codecName = null;
396         int codecType = SOURCE_CODEC_TYPE_INVALID;
397         if (mCodecType != null) {
398             codecName = mCodecType.getCodecName();
399             codecType = mCodecType.getNativeCodecType();
400         }
401 
402         String sampleRateStr = null;
403         if (mSampleRate == SAMPLE_RATE_NONE) {
404             sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
405         }
406         if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
407             sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
408         }
409         if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
410             sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
411         }
412         if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
413             sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
414         }
415         if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
416             sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
417         }
418         if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
419             sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
420         }
421         if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
422             sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
423         }
424 
425         String bitsPerSampleStr = null;
426         if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
427             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
428         }
429         if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
430             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
431         }
432         if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
433             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
434         }
435         if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
436             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
437         }
438 
439         String channelModeStr = null;
440         if (mChannelMode == CHANNEL_MODE_NONE) {
441             channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
442         }
443         if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
444             channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
445         }
446         if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
447             channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
448         }
449 
450         return ("{codecName:" + codecName)
451                 + (",mCodecType:" + codecType)
452                 + (",mCodecPriority:" + mCodecPriority)
453                 + (",mSampleRate:" + String.format("0x%x", mSampleRate) + "(" + sampleRateStr + ")")
454                 + (",mBitsPerSample:"
455                         + String.format("0x%x", mBitsPerSample)
456                         + "("
457                         + bitsPerSampleStr
458                         + ")")
459                 + (",mChannelMode:"
460                         + String.format("0x%x", mChannelMode)
461                         + "("
462                         + channelModeStr
463                         + ")")
464                 + (",mCodecSpecific1:" + mCodecSpecific1)
465                 + (",mCodecSpecific2:" + mCodecSpecific2)
466                 + (",mCodecSpecific3:" + mCodecSpecific3)
467                 + (",mCodecSpecific4:" + mCodecSpecific4)
468                 + "}";
469     }
470 
471     /**
472      * @return 0
473      * @hide
474      */
475     @Override
describeContents()476     public int describeContents() {
477         return 0;
478     }
479 
480     public static final @NonNull Creator<BluetoothCodecConfig> CREATOR =
481             new Creator<>() {
482                 public BluetoothCodecConfig createFromParcel(Parcel in) {
483                     return new BluetoothCodecConfig(in);
484                 }
485 
486                 public BluetoothCodecConfig[] newArray(int size) {
487                     return new BluetoothCodecConfig[size];
488                 }
489             };
490 
491     /**
492      * Flattens the object to a parcel
493      *
494      * @param out The Parcel in which the object should be written
495      * @param flags Additional flags about how the object should be written
496      * @hide
497      */
498     @Override
writeToParcel(Parcel out, int flags)499     public void writeToParcel(Parcel out, int flags) {
500         out.writeInt(getCodecType());
501         out.writeInt(mCodecPriority);
502         out.writeInt(mSampleRate);
503         out.writeInt(mBitsPerSample);
504         out.writeInt(mChannelMode);
505         out.writeLong(mCodecSpecific1);
506         out.writeLong(mCodecSpecific2);
507         out.writeLong(mCodecSpecific3);
508         out.writeLong(mCodecSpecific4);
509     }
510 
511     /**
512      * Returns the codec name converted to {@link String}.
513      *
514      * @hide
515      */
getCodecName(@ourceCodecType int codecType)516     public static @NonNull String getCodecName(@SourceCodecType int codecType) {
517         switch (codecType) {
518             case SOURCE_CODEC_TYPE_SBC:
519                 return "SBC";
520             case SOURCE_CODEC_TYPE_AAC:
521                 return "AAC";
522             case SOURCE_CODEC_TYPE_APTX:
523                 return "aptX";
524             case SOURCE_CODEC_TYPE_APTX_HD:
525                 return "aptX HD";
526             case SOURCE_CODEC_TYPE_LDAC:
527                 return "LDAC";
528             case SOURCE_CODEC_TYPE_LC3:
529                 return "LC3";
530             case SOURCE_CODEC_TYPE_OPUS:
531                 return "Opus";
532             case SOURCE_CODEC_TYPE_INVALID:
533                 return "INVALID CODEC";
534             default:
535                 break;
536         }
537         return "UNKNOWN CODEC(" + codecType + ")";
538     }
539 
540     /**
541      * Returns the source codec type of this config.
542      *
543      * @deprecated use {@link BluetoothCodecConfig#getExtendedCodecType} instead.
544      */
545     @Deprecated
546     @SuppressLint("WrongConstant")
getCodecType()547     public @SourceCodecType int getCodecType() {
548         return mCodecType == null ? SOURCE_CODEC_TYPE_INVALID : mCodecType.getNativeCodecType();
549     }
550 
551     /** Returns the source codec type of this config. */
552     @FlaggedApi(Flags.FLAG_A2DP_OFFLOAD_CODEC_EXTENSIBILITY)
getExtendedCodecType()553     public @Nullable BluetoothCodecType getExtendedCodecType() {
554         return mCodecType;
555     }
556 
557     /**
558      * Checks whether the codec is mandatory.
559      *
560      * <p>The actual mandatory codec type for Android Bluetooth audio is SBC. See {@link
561      * #SOURCE_CODEC_TYPE_SBC}.
562      *
563      * @return {@code true} if the codec is mandatory, {@code false} otherwise
564      */
isMandatoryCodec()565     public boolean isMandatoryCodec() {
566         return mCodecType == null ? false : mCodecType.isMandatoryCodec();
567     }
568 
569     /**
570      * Returns the codec selection priority.
571      *
572      * <p>The codec selection priority is relative to other codecs: larger value means higher
573      * priority.
574      */
getCodecPriority()575     public @CodecPriority int getCodecPriority() {
576         return mCodecPriority;
577     }
578 
579     /**
580      * Sets the codec selection priority.
581      *
582      * <p>The codec selection priority is relative to other codecs: larger value means higher
583      * priority.
584      *
585      * @param codecPriority the priority this codec should have
586      * @hide
587      */
setCodecPriority(@odecPriority int codecPriority)588     public void setCodecPriority(@CodecPriority int codecPriority) {
589         mCodecPriority = codecPriority;
590     }
591 
592     /**
593      * Returns the codec sample rate. The value can be a bitmask with all supported sample rates.
594      */
getSampleRate()595     public @SampleRate int getSampleRate() {
596         return mSampleRate;
597     }
598 
599     /**
600      * Returns the codec bits per sample. The value can be a bitmask with all bits per sample
601      * supported.
602      */
getBitsPerSample()603     public @BitsPerSample int getBitsPerSample() {
604         return mBitsPerSample;
605     }
606 
607     /**
608      * Returns the codec channel mode. The value can be a bitmask with all supported channel modes.
609      */
getChannelMode()610     public @ChannelMode int getChannelMode() {
611         return mChannelMode;
612     }
613 
614     /**
615      * Returns the codec specific value1. As the value and usage differ for each codec, please refer
616      * to the concerned codec specification to obtain the codec specific information.
617      *
618      * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific information
619      * elements.
620      *
621      * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio codec specific
622      * information elements.
623      *
624      * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC codec specific
625      * information elements.
626      *
627      * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family codec specific
628      * information elements.
629      *
630      * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP codec
631      * specific information elements.
632      */
getCodecSpecific1()633     public long getCodecSpecific1() {
634         return mCodecSpecific1;
635     }
636 
637     /**
638      * Returns the codec specific value2. As the value and usage differ for each codec, please refer
639      * to the concerned codec specification to obtain the codec specific information.
640      *
641      * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific information
642      * elements.
643      *
644      * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio codec specific
645      * information elements.
646      *
647      * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC codec specific
648      * information elements.
649      *
650      * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family codec specific
651      * information elements.
652      *
653      * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP codec
654      * specific information elements.
655      */
getCodecSpecific2()656     public long getCodecSpecific2() {
657         return mCodecSpecific2;
658     }
659 
660     /**
661      * Returns the codec specific value3. As the value and usage differ for each codec, please refer
662      * to the concerned codec specification to obtain the codec specific information.
663      *
664      * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific information
665      * elements.
666      *
667      * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio codec specific
668      * information elements.
669      *
670      * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC codec specific
671      * information elements.
672      *
673      * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family codec specific
674      * information elements.
675      *
676      * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP codec
677      * specific information elements.
678      */
getCodecSpecific3()679     public long getCodecSpecific3() {
680         return mCodecSpecific3;
681     }
682 
683     /**
684      * Returns the codec specific value4. As the value and usage differ for each codec, please refer
685      * to the concerned codec specification to obtain the codec specific information.
686      *
687      * <p>See section 4.3.2 of the Bluetooth A2dp specification for SBC codec specific information
688      * elements.
689      *
690      * <p>See section 4.4.2 of the Bluetooth A2dp specification for MPEG-1,2 Audio codec specific
691      * information elements.
692      *
693      * <p>See section 4.5.2 of the Bluetooth A2dp specification for MPEG-2, 4 AAC codec specific
694      * information elements.
695      *
696      * <p>See section 4.6.2 of the Bluetooth A2dp specification for ATRAC family codec specific
697      * information elements.
698      *
699      * <p>See section 4.7.2 of the Bluetooth A2dp specification for Vendor Specific A2DP codec
700      * specific information elements.
701      */
getCodecSpecific4()702     public long getCodecSpecific4() {
703         return mCodecSpecific4;
704     }
705 
706     /**
707      * Checks whether a value set presented by a bitmask has zero or single bit
708      *
709      * @param valueSet the value set presented by a bitmask
710      * @return {@code true} if the valueSet contains zero or single bit, {@code false} otherwise
711      * @hide
712      */
hasSingleBit(int valueSet)713     private static boolean hasSingleBit(int valueSet) {
714         return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
715     }
716 
717     /**
718      * Returns whether the object contains none or single sample rate.
719      *
720      * @hide
721      */
hasSingleSampleRate()722     public boolean hasSingleSampleRate() {
723         return hasSingleBit(mSampleRate);
724     }
725 
726     /**
727      * Returns whether the object contains none or single bits per sample.
728      *
729      * @hide
730      */
hasSingleBitsPerSample()731     public boolean hasSingleBitsPerSample() {
732         return hasSingleBit(mBitsPerSample);
733     }
734 
735     /**
736      * Returns whether the object contains none or single channel mode.
737      *
738      * @hide
739      */
hasSingleChannelMode()740     public boolean hasSingleChannelMode() {
741         return hasSingleBit(mChannelMode);
742     }
743 
744     /**
745      * Checks whether the audio feeding parameters are the same.
746      *
747      * @param other the codec config to compare against
748      * @return {@code true} if the audio feeding parameters are same, {@code false} otherwise
749      * @hide
750      */
sameAudioFeedingParameters(BluetoothCodecConfig other)751     public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
752         return (other != null
753                 && other.mSampleRate == mSampleRate
754                 && other.mBitsPerSample == mBitsPerSample
755                 && other.mChannelMode == mChannelMode);
756     }
757 
758     /**
759      * Checks whether another codec config has the similar feeding parameters. Any parameters with
760      * NONE value will be considered to be a wildcard matching.
761      *
762      * @param other the codec config to compare against
763      * @return {@code true} if the audio feeding parameters are similar, {@code false} otherwise
764      * @hide
765      */
similarCodecFeedingParameters(BluetoothCodecConfig other)766     public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
767         if (other == null || !Objects.equals(mCodecType, other.mCodecType)) {
768             return false;
769         }
770         int sampleRate = other.mSampleRate;
771         if (mSampleRate == SAMPLE_RATE_NONE || sampleRate == SAMPLE_RATE_NONE) {
772             sampleRate = mSampleRate;
773         }
774         int bitsPerSample = other.mBitsPerSample;
775         if (mBitsPerSample == BITS_PER_SAMPLE_NONE || bitsPerSample == BITS_PER_SAMPLE_NONE) {
776             bitsPerSample = mBitsPerSample;
777         }
778         int channelMode = other.mChannelMode;
779         if (mChannelMode == CHANNEL_MODE_NONE || channelMode == CHANNEL_MODE_NONE) {
780             channelMode = mChannelMode;
781         }
782         return sameAudioFeedingParameters(
783                 new BluetoothCodecConfig(
784                         mCodecType, /* priority */
785                         0,
786                         sampleRate,
787                         bitsPerSample,
788                         channelMode,
789                         /* specific1 */ 0, /* specific2 */
790                         0, /* specific3 */
791                         0,
792                         /* specific4 */ 0));
793     }
794 
795     /**
796      * Checks whether the codec specific parameters are the same.
797      *
798      * <p>Currently, only AAC VBR and LDAC Playback Quality on CodecSpecific1 are compared.
799      *
800      * @param other the codec config to compare against
801      * @return {@code true} if the codec specific parameters are the same, {@code false} otherwise
802      * @hide
803      */
sameCodecSpecificParameters(BluetoothCodecConfig other)804     public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
805         if (other == null && !Objects.equals(mCodecType, other.mCodecType)) {
806             return false;
807         }
808         switch (getCodecType()) {
809             case SOURCE_CODEC_TYPE_AAC:
810             case SOURCE_CODEC_TYPE_LDAC:
811             case SOURCE_CODEC_TYPE_LC3:
812             case SOURCE_CODEC_TYPE_OPUS:
813                 if (mCodecSpecific1 != other.mCodecSpecific1) {
814                     return false;
815                 }
816                 // fall through
817             default:
818                 return true;
819         }
820     }
821 
822     /**
823      * Builder for {@link BluetoothCodecConfig}.
824      *
825      * <p>By default, the codec type will be set to {@link
826      * BluetoothCodecConfig#SOURCE_CODEC_TYPE_INVALID}, the codec priority to {@link
827      * BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to {@link
828      * BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to {@link
829      * BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to {@link
830      * BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific values to 0.
831      */
832     public static final class Builder {
833         private @Nullable BluetoothCodecType mCodecType = null;
834         private int mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
835         private int mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
836         private int mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
837         private int mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
838         private long mCodecSpecific1 = 0;
839         private long mCodecSpecific2 = 0;
840         private long mCodecSpecific3 = 0;
841         private long mCodecSpecific4 = 0;
842 
843         /**
844          * Set codec type for Bluetooth codec config.
845          *
846          * @param codecType of this codec
847          * @return the same Builder instance
848          * @deprecated use {@link BluetoothCodecType} instead
849          */
850         @Deprecated
setCodecType(@ourceCodecType int codecType)851         public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
852             mCodecType = BluetoothCodecType.createFromType(codecType);
853             return this;
854         }
855 
856         /**
857          * Set codec type for Bluetooth codec config.
858          *
859          * @param codecType of this codec
860          * @return the same Builder instance
861          */
862         @FlaggedApi(Flags.FLAG_A2DP_OFFLOAD_CODEC_EXTENSIBILITY)
setExtendedCodecType(@ullable BluetoothCodecType codecType)863         public @NonNull Builder setExtendedCodecType(@Nullable BluetoothCodecType codecType) {
864             mCodecType = codecType;
865             return this;
866         }
867 
868         /**
869          * Set codec priority for Bluetooth codec config.
870          *
871          * @param codecPriority of this codec
872          * @return the same Builder instance
873          */
setCodecPriority(@odecPriority int codecPriority)874         public @NonNull Builder setCodecPriority(@CodecPriority int codecPriority) {
875             mCodecPriority = codecPriority;
876             return this;
877         }
878 
879         /**
880          * Set sample rate for Bluetooth codec config.
881          *
882          * @param sampleRate of this codec
883          * @return the same Builder instance
884          */
setSampleRate(@ampleRate int sampleRate)885         public @NonNull Builder setSampleRate(@SampleRate int sampleRate) {
886             mSampleRate = sampleRate;
887             return this;
888         }
889 
890         /**
891          * Set the bits per sample for Bluetooth codec config.
892          *
893          * @param bitsPerSample of this codec
894          * @return the same Builder instance
895          */
setBitsPerSample(@itsPerSample int bitsPerSample)896         public @NonNull Builder setBitsPerSample(@BitsPerSample int bitsPerSample) {
897             mBitsPerSample = bitsPerSample;
898             return this;
899         }
900 
901         /**
902          * Set the channel mode for Bluetooth codec config.
903          *
904          * @param channelMode of this codec
905          * @return the same Builder instance
906          */
setChannelMode(@hannelMode int channelMode)907         public @NonNull Builder setChannelMode(@ChannelMode int channelMode) {
908             mChannelMode = channelMode;
909             return this;
910         }
911 
912         /**
913          * Set the first codec specific values for Bluetooth codec config.
914          *
915          * @param codecSpecific1 codec specific value or 0 if default
916          * @return the same Builder instance
917          */
setCodecSpecific1(long codecSpecific1)918         public @NonNull Builder setCodecSpecific1(long codecSpecific1) {
919             mCodecSpecific1 = codecSpecific1;
920             return this;
921         }
922 
923         /**
924          * Set the second codec specific values for Bluetooth codec config.
925          *
926          * @param codecSpecific2 codec specific value or 0 if default
927          * @return the same Builder instance
928          */
setCodecSpecific2(long codecSpecific2)929         public @NonNull Builder setCodecSpecific2(long codecSpecific2) {
930             mCodecSpecific2 = codecSpecific2;
931             return this;
932         }
933 
934         /**
935          * Set the third codec specific values for Bluetooth codec config.
936          *
937          * @param codecSpecific3 codec specific value or 0 if default
938          * @return the same Builder instance
939          */
setCodecSpecific3(long codecSpecific3)940         public @NonNull Builder setCodecSpecific3(long codecSpecific3) {
941             mCodecSpecific3 = codecSpecific3;
942             return this;
943         }
944 
945         /**
946          * Set the fourth codec specific values for Bluetooth codec config.
947          *
948          * @param codecSpecific4 codec specific value or 0 if default
949          * @return the same Builder instance
950          */
setCodecSpecific4(long codecSpecific4)951         public @NonNull Builder setCodecSpecific4(long codecSpecific4) {
952             mCodecSpecific4 = codecSpecific4;
953             return this;
954         }
955 
956         /**
957          * Build {@link BluetoothCodecConfig}.
958          *
959          * @return new BluetoothCodecConfig built
960          */
build()961         public @NonNull BluetoothCodecConfig build() {
962             return new BluetoothCodecConfig(
963                     mCodecType,
964                     mCodecPriority,
965                     mSampleRate,
966                     mBitsPerSample,
967                     mChannelMode,
968                     mCodecSpecific1,
969                     mCodecSpecific2,
970                     mCodecSpecific3,
971                     mCodecSpecific4);
972         }
973     }
974 }
975