Home | History | Annotate | Download | only in bluetooth
      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.os.Parcel;
     20 import android.os.Parcelable;
     21 
     22 import java.util.Objects;
     23 
     24 /**
     25  * Represents the codec configuration for a Bluetooth A2DP source device.
     26  *
     27  * {@see BluetoothA2dp}
     28  *
     29  * {@hide}
     30  */
     31 public final class BluetoothCodecConfig implements Parcelable {
     32     // Add an entry for each source codec here.
     33     // NOTE: The values should be same as those listed in the following file:
     34     //   hardware/libhardware/include/hardware/bt_av.h
     35     public static final int SOURCE_CODEC_TYPE_SBC = 0;
     36     public static final int SOURCE_CODEC_TYPE_AAC = 1;
     37     public static final int SOURCE_CODEC_TYPE_APTX = 2;
     38     public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
     39     public static final int SOURCE_CODEC_TYPE_LDAC = 4;
     40     public static final int SOURCE_CODEC_TYPE_MAX = 5;
     41 
     42     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
     43 
     44     public static final int CODEC_PRIORITY_DISABLED = -1;
     45     public static final int CODEC_PRIORITY_DEFAULT = 0;
     46     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
     47 
     48     public static final int SAMPLE_RATE_NONE = 0;
     49     public static final int SAMPLE_RATE_44100 = 0x1 << 0;
     50     public static final int SAMPLE_RATE_48000 = 0x1 << 1;
     51     public static final int SAMPLE_RATE_88200 = 0x1 << 2;
     52     public static final int SAMPLE_RATE_96000 = 0x1 << 3;
     53     public static final int SAMPLE_RATE_176400 = 0x1 << 4;
     54     public static final int SAMPLE_RATE_192000 = 0x1 << 5;
     55 
     56     public static final int BITS_PER_SAMPLE_NONE = 0;
     57     public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
     58     public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
     59     public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
     60 
     61     public static final int CHANNEL_MODE_NONE = 0;
     62     public static final int CHANNEL_MODE_MONO = 0x1 << 0;
     63     public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
     64 
     65     private final int mCodecType;
     66     private int mCodecPriority;
     67     private final int mSampleRate;
     68     private final int mBitsPerSample;
     69     private final int mChannelMode;
     70     private final long mCodecSpecific1;
     71     private final long mCodecSpecific2;
     72     private final long mCodecSpecific3;
     73     private final long mCodecSpecific4;
     74 
     75     public BluetoothCodecConfig(int codecType, int codecPriority,
     76             int sampleRate, int bitsPerSample,
     77             int channelMode, long codecSpecific1,
     78             long codecSpecific2, long codecSpecific3,
     79             long codecSpecific4) {
     80         mCodecType = codecType;
     81         mCodecPriority = codecPriority;
     82         mSampleRate = sampleRate;
     83         mBitsPerSample = bitsPerSample;
     84         mChannelMode = channelMode;
     85         mCodecSpecific1 = codecSpecific1;
     86         mCodecSpecific2 = codecSpecific2;
     87         mCodecSpecific3 = codecSpecific3;
     88         mCodecSpecific4 = codecSpecific4;
     89     }
     90 
     91     @Override
     92     public boolean equals(Object o) {
     93         if (o instanceof BluetoothCodecConfig) {
     94             BluetoothCodecConfig other = (BluetoothCodecConfig) o;
     95             return (other.mCodecType == mCodecType
     96                     && other.mCodecPriority == mCodecPriority
     97                     && other.mSampleRate == mSampleRate
     98                     && other.mBitsPerSample == mBitsPerSample
     99                     && other.mChannelMode == mChannelMode
    100                     && other.mCodecSpecific1 == mCodecSpecific1
    101                     && other.mCodecSpecific2 == mCodecSpecific2
    102                     && other.mCodecSpecific3 == mCodecSpecific3
    103                     && other.mCodecSpecific4 == mCodecSpecific4);
    104         }
    105         return false;
    106     }
    107 
    108     @Override
    109     public int hashCode() {
    110         return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
    111                 mBitsPerSample, mChannelMode, mCodecSpecific1,
    112                 mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
    113     }
    114 
    115     /**
    116      * Checks whether the object contains valid codec configuration.
    117      *
    118      * @return true if the object contains valid codec configuration, otherwise false.
    119      */
    120     public boolean isValid() {
    121         return (mSampleRate != SAMPLE_RATE_NONE)
    122                 && (mBitsPerSample != BITS_PER_SAMPLE_NONE)
    123                 && (mChannelMode != CHANNEL_MODE_NONE);
    124     }
    125 
    126     /**
    127      * Adds capability string to an existing string.
    128      *
    129      * @param prevStr the previous string with the capabilities. Can be a null pointer.
    130      * @param capStr the capability string to append to prevStr argument.
    131      * @return the result string in the form "prevStr|capStr".
    132      */
    133     private static String appendCapabilityToString(String prevStr,
    134             String capStr) {
    135         if (prevStr == null) {
    136             return capStr;
    137         }
    138         return prevStr + "|" + capStr;
    139     }
    140 
    141     @Override
    142     public String toString() {
    143         String sampleRateStr = null;
    144         if (mSampleRate == SAMPLE_RATE_NONE) {
    145             sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
    146         }
    147         if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
    148             sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
    149         }
    150         if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
    151             sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
    152         }
    153         if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
    154             sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
    155         }
    156         if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
    157             sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
    158         }
    159         if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
    160             sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
    161         }
    162         if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
    163             sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
    164         }
    165 
    166         String bitsPerSampleStr = null;
    167         if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
    168             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
    169         }
    170         if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
    171             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
    172         }
    173         if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
    174             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
    175         }
    176         if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
    177             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
    178         }
    179 
    180         String channelModeStr = null;
    181         if (mChannelMode == CHANNEL_MODE_NONE) {
    182             channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
    183         }
    184         if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
    185             channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
    186         }
    187         if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
    188             channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
    189         }
    190 
    191         return "{codecName:" + getCodecName()
    192                 + ",mCodecType:" + mCodecType
    193                 + ",mCodecPriority:" + mCodecPriority
    194                 + ",mSampleRate:" + String.format("0x%x", mSampleRate)
    195                 + "(" + sampleRateStr + ")"
    196                 + ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample)
    197                 + "(" + bitsPerSampleStr + ")"
    198                 + ",mChannelMode:" + String.format("0x%x", mChannelMode)
    199                 + "(" + channelModeStr + ")"
    200                 + ",mCodecSpecific1:" + mCodecSpecific1
    201                 + ",mCodecSpecific2:" + mCodecSpecific2
    202                 + ",mCodecSpecific3:" + mCodecSpecific3
    203                 + ",mCodecSpecific4:" + mCodecSpecific4 + "}";
    204     }
    205 
    206     @Override
    207     public int describeContents() {
    208         return 0;
    209     }
    210 
    211     public static final Parcelable.Creator<BluetoothCodecConfig> CREATOR =
    212             new Parcelable.Creator<BluetoothCodecConfig>() {
    213                 public BluetoothCodecConfig createFromParcel(Parcel in) {
    214                     final int codecType = in.readInt();
    215                     final int codecPriority = in.readInt();
    216                     final int sampleRate = in.readInt();
    217                     final int bitsPerSample = in.readInt();
    218                     final int channelMode = in.readInt();
    219                     final long codecSpecific1 = in.readLong();
    220                     final long codecSpecific2 = in.readLong();
    221                     final long codecSpecific3 = in.readLong();
    222                     final long codecSpecific4 = in.readLong();
    223                     return new BluetoothCodecConfig(codecType, codecPriority,
    224                             sampleRate, bitsPerSample,
    225                             channelMode, codecSpecific1,
    226                             codecSpecific2, codecSpecific3,
    227                             codecSpecific4);
    228                 }
    229 
    230                 public BluetoothCodecConfig[] newArray(int size) {
    231                     return new BluetoothCodecConfig[size];
    232                 }
    233             };
    234 
    235     @Override
    236     public void writeToParcel(Parcel out, int flags) {
    237         out.writeInt(mCodecType);
    238         out.writeInt(mCodecPriority);
    239         out.writeInt(mSampleRate);
    240         out.writeInt(mBitsPerSample);
    241         out.writeInt(mChannelMode);
    242         out.writeLong(mCodecSpecific1);
    243         out.writeLong(mCodecSpecific2);
    244         out.writeLong(mCodecSpecific3);
    245         out.writeLong(mCodecSpecific4);
    246     }
    247 
    248     /**
    249      * Gets the codec name.
    250      *
    251      * @return the codec name
    252      */
    253     public String getCodecName() {
    254         switch (mCodecType) {
    255             case SOURCE_CODEC_TYPE_SBC:
    256                 return "SBC";
    257             case SOURCE_CODEC_TYPE_AAC:
    258                 return "AAC";
    259             case SOURCE_CODEC_TYPE_APTX:
    260                 return "aptX";
    261             case SOURCE_CODEC_TYPE_APTX_HD:
    262                 return "aptX HD";
    263             case SOURCE_CODEC_TYPE_LDAC:
    264                 return "LDAC";
    265             case SOURCE_CODEC_TYPE_INVALID:
    266                 return "INVALID CODEC";
    267             default:
    268                 break;
    269         }
    270         return "UNKNOWN CODEC(" + mCodecType + ")";
    271     }
    272 
    273     /**
    274      * Gets the codec type.
    275      * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
    276      *
    277      * @return the codec type
    278      */
    279     public int getCodecType() {
    280         return mCodecType;
    281     }
    282 
    283     /**
    284      * Checks whether the codec is mandatory.
    285      *
    286      * @return true if the codec is mandatory, otherwise false.
    287      */
    288     public boolean isMandatoryCodec() {
    289         return mCodecType == SOURCE_CODEC_TYPE_SBC;
    290     }
    291 
    292     /**
    293      * Gets the codec selection priority.
    294      * The codec selection priority is relative to other codecs: larger value
    295      * means higher priority. If 0, reset to default.
    296      *
    297      * @return the codec priority
    298      */
    299     public int getCodecPriority() {
    300         return mCodecPriority;
    301     }
    302 
    303     /**
    304      * Sets the codec selection priority.
    305      * The codec selection priority is relative to other codecs: larger value
    306      * means higher priority. If 0, reset to default.
    307      *
    308      * @param codecPriority the codec priority
    309      */
    310     public void setCodecPriority(int codecPriority) {
    311         mCodecPriority = codecPriority;
    312     }
    313 
    314     /**
    315      * Gets the codec sample rate. The value can be a bitmask with all
    316      * supported sample rates:
    317      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
    318      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
    319      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
    320      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
    321      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
    322      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
    323      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
    324      *
    325      * @return the codec sample rate
    326      */
    327     public int getSampleRate() {
    328         return mSampleRate;
    329     }
    330 
    331     /**
    332      * Gets the codec bits per sample. The value can be a bitmask with all
    333      * bits per sample supported:
    334      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
    335      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
    336      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
    337      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
    338      *
    339      * @return the codec bits per sample
    340      */
    341     public int getBitsPerSample() {
    342         return mBitsPerSample;
    343     }
    344 
    345     /**
    346      * Gets the codec channel mode. The value can be a bitmask with all
    347      * supported channel modes:
    348      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
    349      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
    350      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
    351      *
    352      * @return the codec channel mode
    353      */
    354     public int getChannelMode() {
    355         return mChannelMode;
    356     }
    357 
    358     /**
    359      * Gets a codec specific value1.
    360      *
    361      * @return a codec specific value1.
    362      */
    363     public long getCodecSpecific1() {
    364         return mCodecSpecific1;
    365     }
    366 
    367     /**
    368      * Gets a codec specific value2.
    369      *
    370      * @return a codec specific value2
    371      */
    372     public long getCodecSpecific2() {
    373         return mCodecSpecific2;
    374     }
    375 
    376     /**
    377      * Gets a codec specific value3.
    378      *
    379      * @return a codec specific value3
    380      */
    381     public long getCodecSpecific3() {
    382         return mCodecSpecific3;
    383     }
    384 
    385     /**
    386      * Gets a codec specific value4.
    387      *
    388      * @return a codec specific value4
    389      */
    390     public long getCodecSpecific4() {
    391         return mCodecSpecific4;
    392     }
    393 
    394     /**
    395      * Checks whether the audio feeding parameters are same.
    396      *
    397      * @param other the codec config to compare against
    398      * @return true if the audio feeding parameters are same, otherwise false
    399      */
    400     public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
    401         return (other != null && other.mSampleRate == mSampleRate
    402                 && other.mBitsPerSample == mBitsPerSample
    403                 && other.mChannelMode == mChannelMode);
    404     }
    405 }
    406