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