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,
    119      * otherwise false.
    120      */
    121     public boolean isValid() {
    122         return (mSampleRate != SAMPLE_RATE_NONE) &&
    123             (mBitsPerSample != BITS_PER_SAMPLE_NONE) &&
    124             (mChannelMode != CHANNEL_MODE_NONE);
    125     }
    126 
    127     /**
    128      * Adds capability string to an existing string.
    129      *
    130      * @param prevStr the previous string with the capabilities. Can be
    131      * a null pointer.
    132      * @param capStr the capability string to append to prevStr argument.
    133      * @return the result string in the form "prevStr|capStr".
    134      */
    135     private static String appendCapabilityToString(String prevStr,
    136                                                    String capStr) {
    137         if (prevStr == null) {
    138             return capStr;
    139         }
    140         return prevStr + "|" + capStr;
    141     }
    142 
    143     @Override
    144     public String toString() {
    145         String sampleRateStr = null;
    146         if (mSampleRate == SAMPLE_RATE_NONE) {
    147             sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
    148         }
    149         if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
    150             sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
    151         }
    152         if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
    153             sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
    154         }
    155         if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
    156             sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
    157         }
    158         if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
    159             sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
    160         }
    161         if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
    162             sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
    163         }
    164         if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
    165             sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
    166         }
    167 
    168         String bitsPerSampleStr = null;
    169         if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
    170             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
    171         }
    172         if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
    173             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
    174         }
    175         if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
    176             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
    177         }
    178         if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
    179             bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
    180         }
    181 
    182         String channelModeStr = null;
    183         if (mChannelMode == CHANNEL_MODE_NONE) {
    184             channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
    185         }
    186         if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
    187             channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
    188         }
    189         if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
    190             channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
    191         }
    192 
    193         return "{codecName:" + getCodecName() +
    194             ",mCodecType:" + mCodecType +
    195             ",mCodecPriority:" + mCodecPriority +
    196             ",mSampleRate:" + String.format("0x%x", mSampleRate) +
    197             "(" + sampleRateStr + ")" +
    198             ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) +
    199             "(" + bitsPerSampleStr + ")" +
    200             ",mChannelMode:" + String.format("0x%x", mChannelMode) +
    201             "(" + channelModeStr + ")" +
    202             ",mCodecSpecific1:" + mCodecSpecific1 +
    203             ",mCodecSpecific2:" + mCodecSpecific2 +
    204             ",mCodecSpecific3:" + mCodecSpecific3 +
    205             ",mCodecSpecific4:" + mCodecSpecific4 + "}";
    206     }
    207 
    208     public int describeContents() {
    209         return 0;
    210     }
    211 
    212     public static final Parcelable.Creator<BluetoothCodecConfig> CREATOR =
    213             new Parcelable.Creator<BluetoothCodecConfig>() {
    214         public BluetoothCodecConfig createFromParcel(Parcel in) {
    215             final int codecType = in.readInt();
    216             final int codecPriority = in.readInt();
    217             final int sampleRate = in.readInt();
    218             final int bitsPerSample = in.readInt();
    219             final int channelMode = in.readInt();
    220             final long codecSpecific1 = in.readLong();
    221             final long codecSpecific2 = in.readLong();
    222             final long codecSpecific3 = in.readLong();
    223             final long codecSpecific4 = in.readLong();
    224             return new BluetoothCodecConfig(codecType, codecPriority,
    225                                             sampleRate, bitsPerSample,
    226                                             channelMode, codecSpecific1,
    227                                             codecSpecific2, codecSpecific3,
    228                                             codecSpecific4);
    229         }
    230         public BluetoothCodecConfig[] newArray(int size) {
    231             return new BluetoothCodecConfig[size];
    232         }
    233     };
    234 
    235     public void writeToParcel(Parcel out, int flags) {
    236         out.writeInt(mCodecType);
    237         out.writeInt(mCodecPriority);
    238         out.writeInt(mSampleRate);
    239         out.writeInt(mBitsPerSample);
    240         out.writeInt(mChannelMode);
    241         out.writeLong(mCodecSpecific1);
    242         out.writeLong(mCodecSpecific2);
    243         out.writeLong(mCodecSpecific3);
    244         out.writeLong(mCodecSpecific4);
    245     }
    246 
    247     /**
    248      * Gets the codec name.
    249      *
    250      * @return the codec name
    251      */
    252     public String getCodecName() {
    253         switch (mCodecType) {
    254         case SOURCE_CODEC_TYPE_SBC:
    255             return "SBC";
    256         case SOURCE_CODEC_TYPE_AAC:
    257             return "AAC";
    258         case SOURCE_CODEC_TYPE_APTX:
    259             return "aptX";
    260         case SOURCE_CODEC_TYPE_APTX_HD:
    261             return "aptX HD";
    262         case SOURCE_CODEC_TYPE_LDAC:
    263             return "LDAC";
    264         case SOURCE_CODEC_TYPE_INVALID:
    265             return "INVALID CODEC";
    266         default:
    267             break;
    268         }
    269         return "UNKNOWN CODEC(" + mCodecType + ")";
    270     }
    271 
    272     /**
    273      * Gets the codec type.
    274      * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
    275      *
    276      * @return the codec type
    277      */
    278     public int getCodecType() {
    279         return mCodecType;
    280     }
    281 
    282     /**
    283      * Checks whether the codec is mandatory.
    284      *
    285      * @return true if the codec is mandatory, otherwise false.
    286      */
    287     public boolean isMandatoryCodec() {
    288         return mCodecType == SOURCE_CODEC_TYPE_SBC;
    289     }
    290 
    291     /**
    292      * Gets the codec selection priority.
    293      * The codec selection priority is relative to other codecs: larger value
    294      * means higher priority. If 0, reset to default.
    295      *
    296      * @return the codec priority
    297      */
    298     public int getCodecPriority() {
    299         return mCodecPriority;
    300     }
    301 
    302     /**
    303      * Sets the codec selection priority.
    304      * The codec selection priority is relative to other codecs: larger value
    305      * means higher priority. If 0, reset to default.
    306      *
    307      * @param codecPriority the codec priority
    308      */
    309     public void setCodecPriority(int codecPriority) {
    310         mCodecPriority = codecPriority;
    311     }
    312 
    313     /**
    314      * Gets the codec sample rate. The value can be a bitmask with all
    315      * supported sample rates:
    316      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
    317      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
    318      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
    319      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
    320      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
    321      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
    322      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
    323      *
    324      * @return the codec sample rate
    325      */
    326     public int getSampleRate() {
    327         return mSampleRate;
    328     }
    329 
    330     /**
    331      * Gets the codec bits per sample. The value can be a bitmask with all
    332      * bits per sample supported:
    333      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
    334      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
    335      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
    336      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
    337      *
    338      * @return the codec bits per sample
    339      */
    340     public int getBitsPerSample() {
    341         return mBitsPerSample;
    342     }
    343 
    344     /**
    345      * Gets the codec channel mode. The value can be a bitmask with all
    346      * supported channel modes:
    347      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
    348      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
    349      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
    350      *
    351      * @return the codec channel mode
    352      */
    353     public int getChannelMode() {
    354         return mChannelMode;
    355     }
    356 
    357     /**
    358      * Gets a codec specific value1.
    359      *
    360      * @return a codec specific value1.
    361      */
    362     public long getCodecSpecific1() {
    363         return mCodecSpecific1;
    364     }
    365 
    366     /**
    367      * Gets a codec specific value2.
    368      *
    369      * @return a codec specific value2
    370      */
    371     public long getCodecSpecific2() {
    372         return mCodecSpecific2;
    373     }
    374 
    375     /**
    376      * Gets a codec specific value3.
    377      *
    378      * @return a codec specific value3
    379      */
    380     public long getCodecSpecific3() {
    381         return mCodecSpecific3;
    382     }
    383 
    384     /**
    385      * Gets a codec specific value4.
    386      *
    387      * @return a codec specific value4
    388      */
    389     public long getCodecSpecific4() {
    390         return mCodecSpecific4;
    391     }
    392 
    393     /**
    394      * Checks whether the audio feeding parameters are same.
    395      *
    396      * @param other the codec config to compare against
    397      * @return true if the audio feeding parameters are same, otherwise false
    398      */
    399     public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
    400         return (other != null && other.mSampleRate == mSampleRate &&
    401                 other.mBitsPerSample == mBitsPerSample &&
    402                 other.mChannelMode == mChannelMode);
    403     }
    404 }
    405