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 BluetoothCodecConfig(int codecType, int codecPriority, int sampleRate, int bitsPerSample, int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4)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 BluetoothCodecConfig(int codecType)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 equals(Object o)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 hashCode()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 */ isValid()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 */ appendCapabilityToString(String prevStr, String capStr)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 toString()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 describeContents()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 writeToParcel(Parcel out, int flags)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 */ getCodecName()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 getCodecType()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 */ isMandatoryCodec()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 getCodecPriority()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 setCodecPriority(int codecPriority)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 getSampleRate()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 getBitsPerSample()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 getChannelMode()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 getCodecSpecific1()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 getCodecSpecific2()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 getCodecSpecific3()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 getCodecSpecific4()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 */ sameAudioFeedingParameters(BluetoothCodecConfig other)449 public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) { 450 return (other != null && other.mSampleRate == mSampleRate 451 && other.mBitsPerSample == mBitsPerSample 452 && other.mChannelMode == mChannelMode); 453 } 454 } 455