From 784e443350fcecbf1addf9b161c20b3c66a22f45 Mon Sep 17 00:00:00 2001 From: Patty Date: Wed, 24 Nov 2021 00:17:41 +0800 Subject: [PATCH] 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 --- .../2.2/IBluetoothAudioProvidersFactory.hal | 22 ++++ .../BluetoothAudioProvidersFactory.cpp | 41 +++++++ .../default/BluetoothAudioProvidersFactory.h | 4 + bluetooth/audio/2.2/types.hal | 42 +++++++ .../BluetoothAudioSupportedCodecsDB_2_2.cpp | 104 ++++++++++++++++++ .../BluetoothAudioSupportedCodecsDB_2_2.h | 5 + 6 files changed, 218 insertions(+) diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal index 7fb5b6cb52..ae9c598dc2 100644 --- a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal +++ b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal @@ -48,4 +48,26 @@ interface IBluetoothAudioProvidersFactory extends @2.1::IBluetoothAudioProviders */ 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); }; diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp index 51ee422845..2fe31d5246 100644 --- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp +++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp @@ -221,6 +221,47 @@ Return BluetoothAudioProvidersFactory::getProviderCapabilities_2_1( return Void(); } +Return BluetoothAudioProvidersFactory::getProviderCapabilities_2_2( + const V2_1::SessionType sessionType, + getProviderCapabilities_2_2_cb _hidl_cb) { + hidl_vec audio_capabilities = + hidl_vec(0); + if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { + std::vector 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 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 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 658249b57b..4f549d93ce 100644 --- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h +++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h @@ -53,6 +53,10 @@ class BluetoothAudioProvidersFactory : public IBluetoothAudioProvidersFactory { const V2_1::SessionType sessionType, getProviderCapabilities_2_1_cb _hidl_cb) override; + Return 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 d5f8a3fc78..8ec366060c 100644 --- a/bluetooth/audio/2.2/types.hal +++ b/bluetooth/audio/2.2/types.hal @@ -19,6 +19,8 @@ package android.hardware.bluetooth.audio@2.2; 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 @@ enum LeAudioMode : uint8_t { 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 @@ safe_union AudioConfiguration { 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 5becdaa2d0..34cfd7efb7 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp +++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp @@ -24,9 +24,59 @@ namespace android { 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 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 supportedLc3CapabilityList = { + kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1}; + +static AudioLocation stereoAudio = static_cast( + 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> + 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 @@ bool IsOffloadLeAudioConfigurationValid( 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 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(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 832161673c..89da6a383f 100644 --- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h +++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h @@ -30,6 +30,11 @@ bool IsOffloadLeAudioConfigurationValid( session_type, const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration& le_audio_codec_config); + +std::vector +GetLeAudioOffloadCodecCapabilities( + const ::android::hardware::bluetooth::audio::V2_1::SessionType& + session_type); } // namespace audio } // namespace bluetooth } // namespace android