Get default provider codec from HAL
1. Add function getProviderCapabilities_2_2
to return audio capability
2. Add function GetLeAudioOffloadCodecCapabilities
to get le audio offload capability
3. Add LeAudioCapability in HAL 2.2
Tag: #feature
Bug: 203535499
Bug: 150670922
Test: atest BluetoothInstrumentationTests
Change-Id: Ied2d0c8c0bdaa4b8d0c149b5164ba346e4df5ae1
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
index 7fb5b6c..ae9c598 100644
--- a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
+++ b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
@@ -48,4 +48,26 @@
*/
openProvider_2_2(SessionType sessionType)
generates (Status status, IBluetoothAudioProvider provider);
+
+ /**
+ * Gets a list of audio capabilities for a session type.
+ *
+ * For software encoding, the PCM capabilities are returned.
+ * For hardware encoding, the supported codecs and their capabilities are
+ * returned.
+ *
+ * @param sessionType The session type (e.g.
+ * A2DP_SOFTWARE_ENCODING_DATAPATH).
+ * @return audioCapabilities A list containing all the capabilities
+ * supported by the sesson type. The capabilities is a list of
+ * available options when configuring the codec for the session.
+ * For software encoding it is the PCM data rate.
+ * For hardware encoding it is the list of supported codecs and their
+ * capabilities.
+ * If a provider isn't supported, an empty list should be returned.
+ * Note: Only one entry should exist per codec when using hardware
+ * encoding.
+ */
+ getProviderCapabilities_2_2(SessionType sessionType)
+ generates (vec<AudioCapabilities> audioCapabilities);
};
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
index 51ee422..2fe31d5 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
@@ -221,6 +221,47 @@
return Void();
}
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_2(
+ const V2_1::SessionType sessionType,
+ getProviderCapabilities_2_2_cb _hidl_cb) {
+ hidl_vec<V2_2::AudioCapabilities> audio_capabilities =
+ hidl_vec<V2_2::AudioCapabilities>(0);
+ if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ std::vector<CodecCapabilities> db_codec_capabilities =
+ android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+ if (db_codec_capabilities.size()) {
+ audio_capabilities.resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+ }
+ }
+ } else if (sessionType == V2_1::SessionType::
+ LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ sessionType == V2_1::SessionType::
+ LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ std::vector<LeAudioCodecCapabilitiesPair> db_codec_capabilities =
+ android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities(
+ sessionType);
+ if (db_codec_capabilities.size()) {
+ audio_capabilities.resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ audio_capabilities[i].leAudioCapabilities(db_codec_capabilities[i]);
+ }
+ }
+ } else if (sessionType != V2_1::SessionType::UNKNOWN) {
+ std::vector<V2_1::PcmParameters> db_pcm_capabilities =
+ android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
+ if (db_pcm_capabilities.size() == 1) {
+ audio_capabilities.resize(1);
+ audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+ }
+ }
+ LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+ << " supports " << audio_capabilities.size() << " codecs";
+ _hidl_cb(audio_capabilities);
+ return Void();
+}
+
IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
const char* /* name */) {
return new BluetoothAudioProvidersFactory();
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
index 658249b..4f549d9 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
@@ -53,6 +53,10 @@
const V2_1::SessionType sessionType,
getProviderCapabilities_2_1_cb _hidl_cb) override;
+ Return<void> getProviderCapabilities_2_2(
+ const V2_1::SessionType sessionType,
+ getProviderCapabilities_2_2_cb _hidl_cb) override;
+
private:
static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal
index d5f8a3f..8ec3660 100644
--- a/bluetooth/audio/2.2/types.hal
+++ b/bluetooth/audio/2.2/types.hal
@@ -19,6 +19,8 @@
import @2.1::Lc3Parameters;
import @2.1::PcmParameters;
import @2.0::CodecConfiguration;
+import @2.0::CodecCapabilities;
+import @2.1::CodecType;
enum LeAudioMode : uint8_t {
UNKNOWN = 0x00,
@@ -26,6 +28,12 @@
BROADCAST = 0x02,
};
+enum AudioLocation : uint8_t {
+ UNKNOWN = 0,
+ FRONT_LEFT = 1,
+ FRONT_RIGHT = 2,
+};
+
struct UnicastStreamMap {
/* The connection handle used for a unicast or a broadcast group. */
uint16_t streamHandle;
@@ -70,3 +78,37 @@
CodecConfiguration codecConfig;
LeAudioConfiguration leAudioConfig;
};
+
+/** Used to specify the capabilities of the different session types */
+safe_union AudioCapabilities {
+ PcmParameters pcmCapabilities;
+ CodecCapabilities codecCapabilities;
+ LeAudioCodecCapabilitiesPair leAudioCapabilities;
+};
+
+/**
+ * Used to specify th le audio capabilities pair of the Hardware offload encode and decode.
+ */
+struct LeAudioCodecCapabilitiesPair{
+ LeAudioMode mode;
+ LeAudioCodecCapability encodeCapability;
+ LeAudioCodecCapability decodeCapability;
+};
+
+/**
+ * Used to specify the le audio capabilities of the codecs supported by Hardware offload
+ * for encode or decode.
+ */
+struct LeAudioCodecCapability {
+ CodecType codecType;
+ AudioLocation supportedChannel;
+
+ // The number of connected device
+ uint8_t deviceCount;
+
+ // Supported channel count for each device
+ uint8_t channelCountPerDevice;
+
+ // Should use safe union when there is more than one codec
+ Lc3Parameters capabilities;
+};
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
index 5becdaa..34cfd7e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
@@ -24,9 +24,59 @@
namespace bluetooth {
namespace audio {
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_1::CodecType;
+using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
+using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using ::android::hardware::bluetooth::audio::V2_2::AudioLocation;
+using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair;
+using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapability;
+using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
using SessionType_2_1 =
::android::hardware::bluetooth::audio::V2_1::SessionType;
+// Stores the list of offload supported capability
+std::vector<LeAudioCodecCapabilitiesPair> kDefaultOffloadLeAudioCapabilities;
+
+static const LeAudioCodecCapability kInvalidLc3Capability = {
+ .codecType = CodecType::UNKNOWN};
+
+// Default Supported Codecs
+// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
+static const Lc3Parameters kLc3Capability_16_1 = {
+ .samplingFrequency = SampleRate::RATE_16000,
+ .frameDuration = Lc3FrameDuration::DURATION_7500US,
+ .octetsPerFrame = 30};
+
+// Default Supported Codecs
+// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
+static const Lc3Parameters kLc3Capability_16_2 = {
+ .samplingFrequency = SampleRate::RATE_16000,
+ .frameDuration = Lc3FrameDuration::DURATION_10000US,
+ .octetsPerFrame = 40};
+
+// Default Supported Codecs
+// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
+static const Lc3Parameters kLc3Capability_48_4 = {
+ .samplingFrequency = SampleRate::RATE_48000,
+ .frameDuration = Lc3FrameDuration::DURATION_10000US,
+ .octetsPerFrame = 120};
+
+static const std::vector<Lc3Parameters> supportedLc3CapabilityList = {
+ kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
+
+static AudioLocation stereoAudio = static_cast<AudioLocation>(
+ AudioLocation::FRONT_LEFT | AudioLocation::FRONT_RIGHT);
+static AudioLocation monoAudio = AudioLocation::UNKNOWN;
+
+// Stores the supported setting of audio location, connected device, and the
+// channel count for each device
+std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
+ supportedDeviceSetting = {std::make_tuple(stereoAudio, 2, 1),
+ std::make_tuple(monoAudio, 1, 2),
+ std::make_tuple(monoAudio, 1, 1)};
+
bool IsOffloadLeAudioConfigurationValid(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type,
@@ -44,6 +94,60 @@
return true;
}
+LeAudioCodecCapability composeLc3Capability(AudioLocation audioLocation,
+ uint8_t deviceCnt,
+ uint8_t channelCount,
+ Lc3Parameters capability) {
+ return LeAudioCodecCapability{.codecType = CodecType::LC3,
+ .supportedChannel = audioLocation,
+ .deviceCount = deviceCnt,
+ .channelCountPerDevice = channelCount,
+ .capabilities = capability};
+}
+
+std::vector<LeAudioCodecCapabilitiesPair> GetLeAudioOffloadCodecCapabilities(
+ const SessionType_2_1& session_type) {
+ if (session_type !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return std::vector<LeAudioCodecCapabilitiesPair>(0);
+ }
+
+ if (kDefaultOffloadLeAudioCapabilities.empty()) {
+ for (auto [audioLocation, deviceCnt, channelCount] :
+ supportedDeviceSetting) {
+ for (auto capability : supportedLc3CapabilityList) {
+ LeAudioCodecCapability lc3Capability = composeLc3Capability(
+ audioLocation, deviceCnt, channelCount, capability);
+ LeAudioCodecCapability lc3MonoCapability =
+ composeLc3Capability(monoAudio, 1, 1, capability);
+
+ // Adds the capability for encode only
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.mode = LeAudioMode::UNICAST,
+ .encodeCapability = lc3Capability,
+ .decodeCapability = kInvalidLc3Capability});
+
+ // Adds the capability for decode only
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.mode = LeAudioMode::UNICAST,
+ .encodeCapability = kInvalidLc3Capability,
+ .decodeCapability = lc3Capability});
+
+ // Adds the capability for the case that encode and decode exist at the
+ // same time
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.mode = LeAudioMode::UNICAST,
+ .encodeCapability = lc3Capability,
+ .decodeCapability = lc3MonoCapability});
+ }
+ }
+ }
+
+ return kDefaultOffloadLeAudioCapabilities;
+}
+
} // namespace audio
} // namespace bluetooth
} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
index 8321616..89da6a3 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
@@ -30,6 +30,11 @@
session_type,
const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
le_audio_codec_config);
+
+std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair>
+GetLeAudioOffloadCodecCapabilities(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type);
} // namespace audio
} // namespace bluetooth
} // namespace android