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