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