/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.bluetooth; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import com.android.bluetooth.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Represents the codec configuration for a Bluetooth LE Audio source device. * *

Contains the source codec type. * *

The source codec type values are the same as those supported by the device hardware. * * @see BluetoothLeAudioCodecConfig */ public final class BluetoothLeAudioCodecConfig implements Parcelable { // Add an entry for each source codec here. /** @hide */ @IntDef( prefix = "SOURCE_CODEC_TYPE_", value = {SOURCE_CODEC_TYPE_LC3, SOURCE_CODEC_TYPE_INVALID}) @Retention(RetentionPolicy.SOURCE) public @interface SourceCodecType {}; public static final int SOURCE_CODEC_TYPE_LC3 = 0; public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; /** @hide */ @IntDef( prefix = "CODEC_PRIORITY_", value = {CODEC_PRIORITY_DISABLED, CODEC_PRIORITY_DEFAULT, CODEC_PRIORITY_HIGHEST}) @Retention(RetentionPolicy.SOURCE) public @interface CodecPriority {} /** * Codec priority disabled. Used to indicate that this codec is disabled and should not be used. */ public static final int CODEC_PRIORITY_DISABLED = -1; /** Codec priority default. Default value used for codec priority. */ public static final int CODEC_PRIORITY_DEFAULT = 0; /** Codec priority highest. Used to indicate the highest priority a codec can have. */ public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; /** @hide */ @IntDef( flag = true, prefix = "SAMPLE_RATE_", value = { SAMPLE_RATE_NONE, SAMPLE_RATE_8000, SAMPLE_RATE_11025, SAMPLE_RATE_16000, SAMPLE_RATE_22050, SAMPLE_RATE_24000, SAMPLE_RATE_32000, SAMPLE_RATE_44100, SAMPLE_RATE_48000, SAMPLE_RATE_88200, SAMPLE_RATE_96000, SAMPLE_RATE_176400, SAMPLE_RATE_192000, SAMPLE_RATE_384000 }) @Retention(RetentionPolicy.SOURCE) public @interface SampleRate {} /** * Codec sample rate 0 Hz. Default value used for codec sample rate. Values are the bit mask as * defined in the Bluetooth Assigned Numbers, Generic Audio, Supported_Sampling_Frequencies * table. */ public static final int SAMPLE_RATE_NONE = 0; /** Codec sample rate 8000 Hz. */ public static final int SAMPLE_RATE_8000 = 0x01 << 0; /** Codec sample rate 11025 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_11025 = 0x01 << 1; /** Codec sample rate 16000 Hz. */ public static final int SAMPLE_RATE_16000 = 0x01 << 2; /** Codec sample rate 22050 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_22050 = 0x01 << 3; /** Codec sample rate 24000 Hz. */ public static final int SAMPLE_RATE_24000 = 0x01 << 4; /** Codec sample rate 32000 Hz. */ public static final int SAMPLE_RATE_32000 = 0x01 << 5; /** Codec sample rate 44100 Hz. */ public static final int SAMPLE_RATE_44100 = 0x01 << 6; /** Codec sample rate 48000 Hz. */ public static final int SAMPLE_RATE_48000 = 0x01 << 7; /** Codec sample rate 88200 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_88200 = 0x01 << 8; /** Codec sample rate 96000 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_96000 = 0x01 << 9; /** Codec sample rate 176400 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_176400 = 0x01 << 10; /** Codec sample rate 192000 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_192000 = 0x01 << 11; /** Codec sample rate 384000 Hz. */ @FlaggedApi(Flags.FLAG_LEAUDIO_ADD_SAMPLING_FREQUENCIES) public static final int SAMPLE_RATE_384000 = 0x01 << 12; /** @hide */ @IntDef( flag = true, prefix = "BITS_PER_SAMPLE_", value = { BITS_PER_SAMPLE_NONE, BITS_PER_SAMPLE_16, BITS_PER_SAMPLE_24, BITS_PER_SAMPLE_32 }) @Retention(RetentionPolicy.SOURCE) public @interface BitsPerSample {} /** Codec bits per sample 0. Default value of the codec bits per sample. */ public static final int BITS_PER_SAMPLE_NONE = 0; /** Codec bits per sample 16. */ public static final int BITS_PER_SAMPLE_16 = 0x01 << 0; /** Codec bits per sample 24. */ public static final int BITS_PER_SAMPLE_24 = 0x01 << 1; /** Codec bits per sample 32. */ public static final int BITS_PER_SAMPLE_32 = 0x01 << 3; /** * Values are the bit mask as defined in the Bluetooth Assigned Numbers, Generic Audio, * Supported_Audio_Channel_Counts table Note: We use only part of it. * * @hide */ @IntDef( flag = true, prefix = "CHANNEL_COUNT_", value = {CHANNEL_COUNT_NONE, CHANNEL_COUNT_1, CHANNEL_COUNT_2}) @Retention(RetentionPolicy.SOURCE) public @interface ChannelCount {} /** Codec channel mode NONE. Default value of the codec channel mode. */ public static final int CHANNEL_COUNT_NONE = 0; /** Codec channel mode MONO. */ public static final int CHANNEL_COUNT_1 = 0x01 << 0; /** Codec channel mode STEREO. */ public static final int CHANNEL_COUNT_2 = 0x01 << 1; /** * Values are the bit mask as defined in the Bluetooth Assigned Numbers, Generic Audio, * Supported_Frame_Durations table * * @hide */ @IntDef( flag = true, prefix = "FRAME_DURATION_", value = {FRAME_DURATION_NONE, FRAME_DURATION_7500, FRAME_DURATION_10000}) @Retention(RetentionPolicy.SOURCE) public @interface FrameDuration {} /** Frame duration 0. Default value of the frame duration. */ public static final int FRAME_DURATION_NONE = 0; /** Frame duration 7500 us. */ public static final int FRAME_DURATION_7500 = 0x01 << 0; /** Frame duration 10000 us. */ public static final int FRAME_DURATION_10000 = 0x01 << 1; private final @SourceCodecType int mCodecType; private final @CodecPriority int mCodecPriority; private final @SampleRate int mSampleRate; private final @BitsPerSample int mBitsPerSample; private final @ChannelCount int mChannelCount; private final @FrameDuration int mFrameDuration; private final int mOctetsPerFrame; private final int mMinOctetsPerFrame; private final int mMaxOctetsPerFrame; /** * Creates a new BluetoothLeAudioCodecConfig. * * @param codecType the source codec type * @param codecPriority the priority of this codec * @param sampleRate the codec sample rate * @param bitsPerSample the bits per sample of this codec * @param channelCount the channel count of this codec * @param frameDuration the frame duration of this codec * @param octetsPerFrame the octets per frame of this codec * @param minOctetsPerFrame the minimum octets per frame of this codec * @param maxOctetsPerFrame the maximum octets per frame of this codec */ private BluetoothLeAudioCodecConfig( @SourceCodecType int codecType, @CodecPriority int codecPriority, @SampleRate int sampleRate, @BitsPerSample int bitsPerSample, @ChannelCount int channelCount, @FrameDuration int frameDuration, int octetsPerFrame, int minOctetsPerFrame, int maxOctetsPerFrame) { mCodecType = codecType; mCodecPriority = codecPriority; mSampleRate = sampleRate; mBitsPerSample = bitsPerSample; mChannelCount = channelCount; mFrameDuration = frameDuration; mOctetsPerFrame = octetsPerFrame; mMinOctetsPerFrame = minOctetsPerFrame; mMaxOctetsPerFrame = maxOctetsPerFrame; } @Override public int describeContents() { return 0; } /** {@link Parcelable.Creator} interface implementation. */ public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public BluetoothLeAudioCodecConfig createFromParcel(Parcel in) { int codecType = in.readInt(); int codecPriority = in.readInt(); int sampleRate = in.readInt(); int bitsPerSample = in.readInt(); int channelCount = in.readInt(); int frameDuration = in.readInt(); int octetsPerFrame = in.readInt(); int minOctetsPerFrame = in.readInt(); int maxOctetsPerFrame = in.readInt(); return new BluetoothLeAudioCodecConfig( codecType, codecPriority, sampleRate, bitsPerSample, channelCount, frameDuration, octetsPerFrame, minOctetsPerFrame, maxOctetsPerFrame); } public BluetoothLeAudioCodecConfig[] newArray(int size) { return new BluetoothLeAudioCodecConfig[size]; } }; @Override public void writeToParcel(@NonNull Parcel out, int flags) { out.writeInt(mCodecType); out.writeInt(mCodecPriority); out.writeInt(mSampleRate); out.writeInt(mBitsPerSample); out.writeInt(mChannelCount); out.writeInt(mFrameDuration); out.writeInt(mOctetsPerFrame); out.writeInt(mMinOctetsPerFrame); out.writeInt(mMaxOctetsPerFrame); } private String sampleRateToString(@SampleRate int sampleRateBit) { switch (sampleRateBit) { case SAMPLE_RATE_NONE: return "None"; case SAMPLE_RATE_8000: return "8 kHz"; case SAMPLE_RATE_11025: return "11.025 kHz"; case SAMPLE_RATE_16000: return "16 kHz"; case SAMPLE_RATE_22050: return "22.05 kHz"; case SAMPLE_RATE_24000: return "24 kHz"; case SAMPLE_RATE_32000: return "32 kHz"; case SAMPLE_RATE_44100: return "44.1 kHz"; case SAMPLE_RATE_48000: return "48 kHz"; case SAMPLE_RATE_88200: return "88.2 kHz"; case SAMPLE_RATE_96000: return "96 kHz"; case SAMPLE_RATE_176400: return "176.4 kHz"; case SAMPLE_RATE_192000: return "192 kHz"; case SAMPLE_RATE_384000: return "384 kHz"; default: return "Unknown bit " + sampleRateBit; } } private String frameDurationToString(@FrameDuration int frameDurationBit) { switch (frameDurationBit) { case FRAME_DURATION_NONE: return "None"; case FRAME_DURATION_7500: return "7.5 ms"; case FRAME_DURATION_10000: return "10 ms"; default: return "Unknown bit " + frameDurationBit; } } @Override public String toString() { return "{codecName:" + getCodecName() + ",mCodecType:" + mCodecType + ",mCodecPriority:" + mCodecPriority + ",mSampleRate:" + sampleRateToString(mSampleRate) + ",mBitsPerSample:" + mBitsPerSample + ",mChannelCountBitMask:" + mChannelCount + ",mFrameDuration:" + frameDurationToString(mFrameDuration) + ",mOctetsPerFrame:" + mOctetsPerFrame + ",mMinOctetsPerFrame:" + mMinOctetsPerFrame + ",mMaxOctetsPerFrame:" + mMaxOctetsPerFrame + "}"; } /** * Gets the codec type. * * @return the codec type */ public @SourceCodecType int getCodecType() { return mCodecType; } /** * Gets the codec name. * * @return the codec name */ public @NonNull String getCodecName() { switch (mCodecType) { case SOURCE_CODEC_TYPE_LC3: return "LC3"; case SOURCE_CODEC_TYPE_INVALID: return "INVALID CODEC"; default: break; } return "UNKNOWN CODEC(" + mCodecType + ")"; } /** * Returns the codec selection priority. * *

The codec selection priority is relative to other codecs: larger value means higher * priority. */ public @CodecPriority int getCodecPriority() { return mCodecPriority; } /** Returns the codec sample rate. */ public @SampleRate int getSampleRate() { return mSampleRate; } /** Returns the codec bits per sample. */ public @BitsPerSample int getBitsPerSample() { return mBitsPerSample; } /** Returns the codec channel mode. */ public @ChannelCount int getChannelCount() { return mChannelCount; } /** Returns the frame duration. */ public @FrameDuration int getFrameDuration() { return mFrameDuration; } /** Returns the octets per frame */ public int getOctetsPerFrame() { return mOctetsPerFrame; } /** Returns the minimum octets per frame */ public int getMinOctetsPerFrame() { return mMinOctetsPerFrame; } /** Returns the maximum octets per frame */ public int getMaxOctetsPerFrame() { return mMaxOctetsPerFrame; } @Override public boolean equals(@Nullable Object o) { if (o instanceof BluetoothLeAudioCodecConfig) { BluetoothLeAudioCodecConfig other = (BluetoothLeAudioCodecConfig) o; return (other.getCodecType() == mCodecType && other.getCodecPriority() == mCodecPriority && other.getSampleRate() == mSampleRate && other.getBitsPerSample() == mBitsPerSample && other.getChannelCount() == mChannelCount && other.getFrameDuration() == mFrameDuration && other.getOctetsPerFrame() == mOctetsPerFrame && other.getMinOctetsPerFrame() == mMinOctetsPerFrame && other.getMaxOctetsPerFrame() == mMaxOctetsPerFrame); } return false; } /** * Returns a hash representation of this BluetoothLeAudioCodecConfig based on all the config * values. */ @Override public int hashCode() { return Objects.hash( mCodecType, mCodecPriority, mSampleRate, mBitsPerSample, mChannelCount, mFrameDuration, mOctetsPerFrame, mMinOctetsPerFrame, mMaxOctetsPerFrame); } /** * Builder for {@link BluetoothLeAudioCodecConfig}. * *

By default, the codec type will be set to {@link * BluetoothLeAudioCodecConfig#SOURCE_CODEC_TYPE_INVALID} */ public static final class Builder { private int mCodecType = BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID; private int mCodecPriority = BluetoothLeAudioCodecConfig.CODEC_PRIORITY_DEFAULT; private int mSampleRate = BluetoothLeAudioCodecConfig.SAMPLE_RATE_NONE; private int mBitsPerSample = BluetoothLeAudioCodecConfig.BITS_PER_SAMPLE_NONE; private int mChannelCount = BluetoothLeAudioCodecConfig.CHANNEL_COUNT_NONE; private int mFrameDuration = BluetoothLeAudioCodecConfig.FRAME_DURATION_NONE; private int mOctetsPerFrame = 0; private int mMinOctetsPerFrame = 0; private int mMaxOctetsPerFrame = 0; public Builder() {} public Builder(@NonNull BluetoothLeAudioCodecConfig config) { mCodecType = config.getCodecType(); mCodecPriority = config.getCodecPriority(); mSampleRate = config.getSampleRate(); mBitsPerSample = config.getBitsPerSample(); mChannelCount = config.getChannelCount(); mFrameDuration = config.getFrameDuration(); mOctetsPerFrame = config.getOctetsPerFrame(); mMinOctetsPerFrame = config.getMinOctetsPerFrame(); mMaxOctetsPerFrame = config.getMaxOctetsPerFrame(); } /** * Set codec type for Bluetooth LE audio codec config. * * @param codecType of this codec * @return the same Builder instance */ public @NonNull Builder setCodecType(@SourceCodecType int codecType) { mCodecType = codecType; return this; } /** * Set codec priority for Bluetooth LE audio codec config. * * @param codecPriority of this codec * @return the same Builder instance */ public @NonNull Builder setCodecPriority(@CodecPriority int codecPriority) { mCodecPriority = codecPriority; return this; } /** * Set sample rate for Bluetooth LE audio codec config. * * @param sampleRate of this codec * @return the same Builder instance */ public @NonNull Builder setSampleRate(@SampleRate int sampleRate) { mSampleRate = sampleRate; return this; } /** * Set the bits per sample for LE audio codec config. * * @param bitsPerSample of this codec * @return the same Builder instance */ public @NonNull Builder setBitsPerSample(@BitsPerSample int bitsPerSample) { mBitsPerSample = bitsPerSample; return this; } /** * Set the channel count for Bluetooth LE audio codec config. * * @param channelCount of this codec * @return the same Builder instance */ public @NonNull Builder setChannelCount(@ChannelCount int channelCount) { mChannelCount = channelCount; return this; } /** * Set the frame duration for Bluetooth LE audio codec config. * * @param frameDuration of this codec * @return the same Builder instance */ public @NonNull Builder setFrameDuration(@FrameDuration int frameDuration) { mFrameDuration = frameDuration; return this; } /** * Set the octets per frame for Bluetooth LE audio codec config. * * @param octetsPerFrame of this codec * @return the same Builder instance */ public @NonNull Builder setOctetsPerFrame(int octetsPerFrame) { mOctetsPerFrame = octetsPerFrame; return this; } /** * Set the minimum octets per frame for Bluetooth LE audio codec config. * * @param minOctetsPerFrame of this codec * @return the same Builder instance */ public @NonNull Builder setMinOctetsPerFrame(int minOctetsPerFrame) { mMinOctetsPerFrame = minOctetsPerFrame; return this; } /** * Set the maximum octets per frame for Bluetooth LE audio codec config. * * @param maxOctetsPerFrame of this codec * @return the same Builder instance */ public @NonNull Builder setMaxOctetsPerFrame(int maxOctetsPerFrame) { mMaxOctetsPerFrame = maxOctetsPerFrame; return this; } /** * Build {@link BluetoothLeAudioCodecConfig}. * * @return new BluetoothLeAudioCodecConfig built */ public @NonNull BluetoothLeAudioCodecConfig build() { return new BluetoothLeAudioCodecConfig( mCodecType, mCodecPriority, mSampleRate, mBitsPerSample, mChannelCount, mFrameDuration, mOctetsPerFrame, mMinOctetsPerFrame, mMaxOctetsPerFrame); } } }