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 BluetoothCodecConfig(int codecType, int codecPriority, int sampleRate, int bitsPerSample, int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4)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 equals(Object o)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 hashCode()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 */ isValid()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 */ appendCapabilityToString(String prevStr, String capStr)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 toString()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 describeContents()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 writeToParcel(Parcel out, int flags)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 */ getCodecName()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 */ getCodecType()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 */ isMandatoryCodec()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 */ getCodecPriority()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 */ setCodecPriority(int codecPriority)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 */ getSampleRate()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 */ getBitsPerSample()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 */ getChannelMode()353 public int getChannelMode() { 354 return mChannelMode; 355 } 356 357 /** 358 * Gets a codec specific value1. 359 * 360 * @return a codec specific value1. 361 */ getCodecSpecific1()362 public long getCodecSpecific1() { 363 return mCodecSpecific1; 364 } 365 366 /** 367 * Gets a codec specific value2. 368 * 369 * @return a codec specific value2 370 */ getCodecSpecific2()371 public long getCodecSpecific2() { 372 return mCodecSpecific2; 373 } 374 375 /** 376 * Gets a codec specific value3. 377 * 378 * @return a codec specific value3 379 */ getCodecSpecific3()380 public long getCodecSpecific3() { 381 return mCodecSpecific3; 382 } 383 384 /** 385 * Gets a codec specific value4. 386 * 387 * @return a codec specific value4 388 */ getCodecSpecific4()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 */ sameAudioFeedingParameters(BluetoothCodecConfig other)399 public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) { 400 return (other != null && other.mSampleRate == mSampleRate && 401 other.mBitsPerSample == mBitsPerSample && 402 other.mChannelMode == mChannelMode); 403 } 404 } 405