diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl index baec9c2109..33a3187c3b 100644 --- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl +++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl @@ -44,4 +44,6 @@ enum SessionType { LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH = 7, LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH = 8, LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 9, + A2DP_SOFTWARE_DECODING_DATAPATH = 10, + A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH = 11, } diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl index 95beee7489..7acb5c6e49 100644 --- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl +++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl @@ -62,4 +62,12 @@ enum SessionType { * Audio broadcast channels. This is a control path only. */ LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH, + /** + * A2DP legacy that AVDTP media is decoded by Bluetooth Stack + */ + A2DP_SOFTWARE_DECODING_DATAPATH, + /** + * The decoding of AVDTP media is done by HW and there is control only + */ + A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH, } diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp index 4b4713d036..2d0d8c9e96 100644 --- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp +++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp @@ -28,10 +28,18 @@ namespace hardware { namespace bluetooth { namespace audio { -A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() { +A2dpOffloadEncodingAudioProvider::A2dpOffloadEncodingAudioProvider() + : A2dpOffloadAudioProvider() { session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH; } +A2dpOffloadDecodingAudioProvider::A2dpOffloadDecodingAudioProvider() + : A2dpOffloadAudioProvider() { + session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH; +} + +A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {} + bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) { return (session_type == session_type_); } diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h index 4621e8530f..e6f188bda6 100644 --- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h +++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h @@ -40,6 +40,16 @@ class A2dpOffloadAudioProvider : public BluetoothAudioProvider { ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; }; +class A2dpOffloadEncodingAudioProvider : public A2dpOffloadAudioProvider { + public: + A2dpOffloadEncodingAudioProvider(); +}; + +class A2dpOffloadDecodingAudioProvider : public A2dpOffloadAudioProvider { + public: + A2dpOffloadDecodingAudioProvider(); +}; + } // namespace audio } // namespace bluetooth } // namespace hardware diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp index 59df3a9901..bd2da95b04 100644 --- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp +++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp @@ -40,6 +40,16 @@ static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount; static constexpr uint32_t kBufferCount = 2; // double buffer static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount; +A2dpSoftwareEncodingAudioProvider::A2dpSoftwareEncodingAudioProvider() + : A2dpSoftwareAudioProvider() { + session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH; +} + +A2dpSoftwareDecodingAudioProvider::A2dpSoftwareDecodingAudioProvider() + : A2dpSoftwareAudioProvider() { + session_type_ = SessionType::A2DP_SOFTWARE_DECODING_DATAPATH; +} + A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider() : BluetoothAudioProvider(), data_mq_(nullptr) { LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize @@ -48,7 +58,6 @@ A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider() new DataMQ(kDataMqSize, /* EventFlag */ true)); if (data_mq && data_mq->isValid()) { data_mq_ = std::move(data_mq); - session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH; } else { ALOGE_IF(!data_mq, "failed to allocate data MQ"); ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid"); diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h index 10f533ab20..3ebecf2b0c 100644 --- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h +++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h @@ -43,6 +43,16 @@ class A2dpSoftwareAudioProvider : public BluetoothAudioProvider { ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override; }; +class A2dpSoftwareEncodingAudioProvider : public A2dpSoftwareAudioProvider { + public: + A2dpSoftwareEncodingAudioProvider(); +}; + +class A2dpSoftwareDecodingAudioProvider : public A2dpSoftwareAudioProvider { + public: + A2dpSoftwareDecodingAudioProvider(); +}; + } // namespace audio } // namespace bluetooth } // namespace hardware diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp index 1e1680a4fd..91731d4160 100644 --- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp +++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp @@ -44,10 +44,10 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider( switch (session_type) { case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH: - provider = ndk::SharedRefBase::make(); + provider = ndk::SharedRefBase::make(); break; case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: - provider = ndk::SharedRefBase::make(); + provider = ndk::SharedRefBase::make(); break; case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH: provider = ndk::SharedRefBase::make(); @@ -72,6 +72,12 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider( provider = ndk::SharedRefBase::make(); break; + case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: + provider = ndk::SharedRefBase::make(); + break; + case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: + provider = ndk::SharedRefBase::make(); + break; default: provider = nullptr; break; @@ -90,7 +96,8 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider( ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities( const SessionType session_type, std::vector* _aidl_return) { - if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { auto codec_capabilities = BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type); _aidl_return->resize(codec_capabilities.size()); diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp index 18352a08bd..b599365d21 100644 --- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp +++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp @@ -201,7 +201,8 @@ class BluetoothAudioProviderFactoryAidl ASSERT_EQ(temp_provider_capabilities_[0].getTag(), AudioCapabilities::pcmCapabilities); } break; - case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: { + case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: { std::unordered_set codec_types; // empty capability means offload is unsupported for (auto& audio_capability : temp_provider_capabilities_) { @@ -250,6 +251,16 @@ class BluetoothAudioProviderFactoryAidl AudioCapabilities::leAudioCapabilities); } } break; + case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: { + if (!temp_provider_capabilities_.empty()) { + ASSERT_EQ(temp_provider_capabilities_.size(), 1); + ASSERT_EQ(temp_provider_capabilities_[0].getTag(), + AudioCapabilities::pcmCapabilities); + } + } break; + default: { + ASSERT_TRUE(temp_provider_capabilities_.empty()); + } } } @@ -266,7 +277,7 @@ class BluetoothAudioProviderFactoryAidl ASSERT_NE(audio_provider_, nullptr); audio_port_ = ndk::SharedRefBase::make(); } else { - // Hardware offloading is optional + // optional session type ASSERT_TRUE( session_type == SessionType::UNKNOWN || session_type == @@ -277,147 +288,14 @@ class BluetoothAudioProviderFactoryAidl SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || session_type == SessionType:: - LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type == + SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH || + session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH); ASSERT_EQ(audio_provider_, nullptr); } } - bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) { - if (temp_provider_capabilities_.size() != 1 || - temp_provider_capabilities_[0].getTag() != - AudioCapabilities::pcmCapabilities) { - return false; - } - auto pcm_capability = temp_provider_capabilities_[0] - .get(); - return (contained_in_vector(pcm_capability.channelMode, - pcm_config.channelMode) && - contained_in_vector(pcm_capability.sampleRateHz, - pcm_config.sampleRateHz) && - contained_in_vector(pcm_capability.bitsPerSample, - pcm_config.bitsPerSample)); - } - - std::shared_ptr provider_factory_; - std::shared_ptr audio_provider_; - std::shared_ptr audio_port_; - std::vector temp_provider_capabilities_; - - static constexpr SessionType kSessionTypes[] = { - SessionType::UNKNOWN, - SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH, - SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH, - SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH, - SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH, - SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH, - SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH, - SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH, - SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH, - SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH, - }; -}; - -/** - * Test whether we can get the FactoryService from HIDL - */ -TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {} - -/** - * Test whether we can open a provider for each provider returned by - * getProviderCapabilities() with non-empty capabalities - */ -TEST_P(BluetoothAudioProviderFactoryAidl, - OpenProviderAndCheckCapabilitiesBySession) { - for (auto session_type : kSessionTypes) { - GetProviderCapabilitiesHelper(session_type); - OpenProviderHelper(session_type); - // We must be able to open a provider if its getProviderCapabilities() - // returns non-empty list. - EXPECT_TRUE(temp_provider_capabilities_.empty() || - audio_provider_ != nullptr); - } -} - -/** - * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH - */ -class BluetoothAudioProviderA2dpSoftwareAidl - : public BluetoothAudioProviderFactoryAidl { - public: - virtual void SetUp() override { - BluetoothAudioProviderFactoryAidl::SetUp(); - GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); - OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); - ASSERT_NE(audio_provider_, nullptr); - } - - virtual void TearDown() override { - audio_port_ = nullptr; - audio_provider_ = nullptr; - BluetoothAudioProviderFactoryAidl::TearDown(); - } -}; - -/** - * Test whether we can open a provider of type - */ -TEST_P(BluetoothAudioProviderA2dpSoftwareAidl, OpenA2dpSoftwareProvider) {} - -/** - * Test whether each provider of type - * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with - * different PCM config - */ -TEST_P(BluetoothAudioProviderA2dpSoftwareAidl, - StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) { - for (auto sample_rate : a2dp_sample_rates) { - for (auto bits_per_sample : a2dp_bits_per_samples) { - for (auto channel_mode : a2dp_channel_modes) { - PcmConfiguration pcm_config{ - .sampleRateHz = sample_rate, - .bitsPerSample = bits_per_sample, - .channelMode = channel_mode, - }; - bool is_codec_config_valid = IsPcmConfigSupported(pcm_config); - DataMQDesc mq_desc; - auto aidl_retval = audio_provider_->startSession( - audio_port_, AudioConfiguration(pcm_config), latency_modes, - &mq_desc); - DataMQ data_mq(mq_desc); - - EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid); - if (is_codec_config_valid) { - EXPECT_TRUE(data_mq.isValid()); - } - EXPECT_TRUE(audio_provider_->endSession().isOk()); - } - } - } -} - -/** - * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH - */ -class BluetoothAudioProviderA2dpHardwareAidl - : public BluetoothAudioProviderFactoryAidl { - public: - virtual void SetUp() override { - BluetoothAudioProviderFactoryAidl::SetUp(); - GetProviderCapabilitiesHelper( - SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); - OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); - ASSERT_TRUE(temp_provider_capabilities_.empty() || - audio_provider_ != nullptr); - } - - virtual void TearDown() override { - audio_port_ = nullptr; - audio_provider_ = nullptr; - BluetoothAudioProviderFactoryAidl::TearDown(); - } - - bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); } - void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) { temp_codec_capabilities_ = nullptr; for (auto& codec_capability : temp_provider_capabilities_) { @@ -641,23 +519,163 @@ class BluetoothAudioProviderA2dpHardwareAidl return lc3_codec_specifics; } + bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) { + if (temp_provider_capabilities_.size() != 1 || + temp_provider_capabilities_[0].getTag() != + AudioCapabilities::pcmCapabilities) { + return false; + } + auto pcm_capability = temp_provider_capabilities_[0] + .get(); + return (contained_in_vector(pcm_capability.channelMode, + pcm_config.channelMode) && + contained_in_vector(pcm_capability.sampleRateHz, + pcm_config.sampleRateHz) && + contained_in_vector(pcm_capability.bitsPerSample, + pcm_config.bitsPerSample)); + } + + std::shared_ptr provider_factory_; + std::shared_ptr audio_provider_; + std::shared_ptr audio_port_; + std::vector temp_provider_capabilities_; + // temp storage saves the specified codec capability by // GetOffloadCodecCapabilityHelper() CodecCapabilities* temp_codec_capabilities_; + + static constexpr SessionType kSessionTypes[] = { + SessionType::UNKNOWN, + SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH, + SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH, + SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH, + SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH, + SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH, + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH, + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH, + SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH, + SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH, + SessionType::A2DP_SOFTWARE_DECODING_DATAPATH, + SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH, + }; +}; + +/** + * Test whether we can get the FactoryService from HIDL + */ +TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {} + +/** + * Test whether we can open a provider for each provider returned by + * getProviderCapabilities() with non-empty capabalities + */ +TEST_P(BluetoothAudioProviderFactoryAidl, + OpenProviderAndCheckCapabilitiesBySession) { + for (auto session_type : kSessionTypes) { + GetProviderCapabilitiesHelper(session_type); + OpenProviderHelper(session_type); + // We must be able to open a provider if its getProviderCapabilities() + // returns non-empty list. + EXPECT_TRUE(temp_provider_capabilities_.empty() || + audio_provider_ != nullptr); + } +} + +/** + * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH + */ +class BluetoothAudioProviderA2dpEncodingSoftwareAidl + : public BluetoothAudioProviderFactoryAidl { + public: + virtual void SetUp() override { + BluetoothAudioProviderFactoryAidl::SetUp(); + GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); + OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); + ASSERT_NE(audio_provider_, nullptr); + } + + virtual void TearDown() override { + audio_port_ = nullptr; + audio_provider_ = nullptr; + BluetoothAudioProviderFactoryAidl::TearDown(); + } }; /** * Test whether we can open a provider of type */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, OpenA2dpHardwareProvider) {} +TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl, + OpenA2dpEncodingSoftwareProvider) {} + +/** + * Test whether each provider of type + * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with + * different PCM config + */ +TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl, + StartAndEndA2dpEncodingSoftwareSessionWithPossiblePcmConfig) { + for (auto sample_rate : a2dp_sample_rates) { + for (auto bits_per_sample : a2dp_bits_per_samples) { + for (auto channel_mode : a2dp_channel_modes) { + PcmConfiguration pcm_config{ + .sampleRateHz = sample_rate, + .bitsPerSample = bits_per_sample, + .channelMode = channel_mode, + }; + bool is_codec_config_valid = IsPcmConfigSupported(pcm_config); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(pcm_config), latency_modes, + &mq_desc); + DataMQ data_mq(mq_desc); + + EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid); + if (is_codec_config_valid) { + EXPECT_TRUE(data_mq.isValid()); + } + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } + } + } +} + +/** + * openProvider A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH + */ +class BluetoothAudioProviderA2dpEncodingHardwareAidl + : public BluetoothAudioProviderFactoryAidl { + public: + virtual void SetUp() override { + BluetoothAudioProviderFactoryAidl::SetUp(); + GetProviderCapabilitiesHelper( + SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + ASSERT_TRUE(temp_provider_capabilities_.empty() || + audio_provider_ != nullptr); + } + + virtual void TearDown() override { + audio_port_ = nullptr; + audio_provider_ = nullptr; + BluetoothAudioProviderFactoryAidl::TearDown(); + } + + bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); } +}; + +/** + * Test whether we can open a provider of type + */ +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + OpenA2dpEncodingHardwareProvider) {} /** * Test whether each provider of type * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * SBC hardware encoding config */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, - StartAndEndA2dpSbcHardwareSession) { +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + StartAndEndA2dpSbcEncodingHardwareSession) { if (!IsOffloadSupported()) { return; } @@ -686,8 +704,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl, * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * AAC hardware encoding config */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, - StartAndEndA2dpAacHardwareSession) { +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + StartAndEndA2dpAacEncodingHardwareSession) { if (!IsOffloadSupported()) { return; } @@ -716,8 +734,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl, * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * LDAC hardware encoding config */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, - StartAndEndA2dpLdacHardwareSession) { +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + StartAndEndA2dpLdacEncodingHardwareSession) { if (!IsOffloadSupported()) { return; } @@ -746,8 +764,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl, * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * LDAC hardware encoding config */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, - StartAndEndA2dpLc3HardwareSession) { +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + StartAndEndA2dpLc3EncodingHardwareSession) { if (!IsOffloadSupported()) { return; } @@ -776,8 +794,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl, * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * AptX hardware encoding config */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, - StartAndEndA2dpAptxHardwareSession) { +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + StartAndEndA2dpAptxEncodingHardwareSession) { if (!IsOffloadSupported()) { return; } @@ -812,8 +830,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl, * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * an invalid codec config */ -TEST_P(BluetoothAudioProviderA2dpHardwareAidl, - StartAndEndA2dpHardwareSessionInvalidCodecConfig) { +TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl, + StartAndEndA2dpEncodingHardwareSessionInvalidCodecConfig) { if (!IsOffloadSupported()) { return; } @@ -1588,6 +1606,314 @@ TEST_P( } } +/** + * openProvider A2DP_SOFTWARE_DECODING_DATAPATH + */ +class BluetoothAudioProviderA2dpDecodingSoftwareAidl + : public BluetoothAudioProviderFactoryAidl { + public: + virtual void SetUp() override { + BluetoothAudioProviderFactoryAidl::SetUp(); + GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH); + OpenProviderHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH); + ASSERT_TRUE(temp_provider_capabilities_.empty() || + audio_provider_ != nullptr); + } + + virtual void TearDown() override { + audio_port_ = nullptr; + audio_provider_ = nullptr; + BluetoothAudioProviderFactoryAidl::TearDown(); + } +}; + +/** + * Test whether we can open a provider of type + */ +TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl, + OpenA2dpDecodingSoftwareProvider) {} + +/** + * Test whether each provider of type + * SessionType::A2DP_SOFTWARE_DECODING_DATAPATH can be started and stopped with + * different PCM config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl, + StartAndEndA2dpDecodingSoftwareSessionWithPossiblePcmConfig) { + for (auto sample_rate : a2dp_sample_rates) { + for (auto bits_per_sample : a2dp_bits_per_samples) { + for (auto channel_mode : a2dp_channel_modes) { + PcmConfiguration pcm_config{ + .sampleRateHz = sample_rate, + .bitsPerSample = bits_per_sample, + .channelMode = channel_mode, + }; + bool is_codec_config_valid = IsPcmConfigSupported(pcm_config); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(pcm_config), latency_modes, + &mq_desc); + DataMQ data_mq(mq_desc); + + EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid); + if (is_codec_config_valid) { + EXPECT_TRUE(data_mq.isValid()); + } + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } + } + } +} + +/** + * openProvider A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH + */ +class BluetoothAudioProviderA2dpDecodingHardwareAidl + : public BluetoothAudioProviderFactoryAidl { + public: + virtual void SetUp() override { + BluetoothAudioProviderFactoryAidl::SetUp(); + GetProviderCapabilitiesHelper( + SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH); + OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH); + ASSERT_TRUE(temp_provider_capabilities_.empty() || + audio_provider_ != nullptr); + } + + virtual void TearDown() override { + audio_port_ = nullptr; + audio_provider_ = nullptr; + BluetoothAudioProviderFactoryAidl::TearDown(); + } + + bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); } +}; + +/** + * Test whether we can open a provider of type + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + OpenA2dpDecodingHardwareProvider) {} + +/** + * Test whether each provider of type + * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with + * SBC hardware encoding config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + StartAndEndA2dpSbcDecodingHardwareSession) { + if (!IsOffloadSupported()) { + return; + } + + CodecConfiguration codec_config = { + .codecType = CodecType::SBC, + .encodedAudioBitrate = 328000, + .peerMtu = 1005, + .isScmstEnabled = false, + }; + auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true); + + for (auto& codec_specific : sbc_codec_specifics) { + copy_codec_specific(codec_config.config, codec_specific); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc); + + ASSERT_TRUE(aidl_retval.isOk()); + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } +} + +/** + * Test whether each provider of type + * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with + * AAC hardware encoding config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + StartAndEndA2dpAacDecodingHardwareSession) { + if (!IsOffloadSupported()) { + return; + } + + CodecConfiguration codec_config = { + .codecType = CodecType::AAC, + .encodedAudioBitrate = 320000, + .peerMtu = 1005, + .isScmstEnabled = false, + }; + auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true); + + for (auto& codec_specific : aac_codec_specifics) { + copy_codec_specific(codec_config.config, codec_specific); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc); + + ASSERT_TRUE(aidl_retval.isOk()); + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } +} + +/** + * Test whether each provider of type + * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with + * LDAC hardware encoding config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + StartAndEndA2dpLdacDecodingHardwareSession) { + if (!IsOffloadSupported()) { + return; + } + + CodecConfiguration codec_config = { + .codecType = CodecType::LDAC, + .encodedAudioBitrate = 990000, + .peerMtu = 1005, + .isScmstEnabled = false, + }; + auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true); + + for (auto& codec_specific : ldac_codec_specifics) { + copy_codec_specific(codec_config.config, codec_specific); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc); + + ASSERT_TRUE(aidl_retval.isOk()); + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } +} + +/** + * Test whether each provider of type + * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with + * LDAC hardware encoding config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + StartAndEndA2dpLc3DecodingHardwareSession) { + if (!IsOffloadSupported()) { + return; + } + + CodecConfiguration codec_config = { + .codecType = CodecType::LC3, + .encodedAudioBitrate = 990000, + .peerMtu = 1005, + .isScmstEnabled = false, + }; + auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true); + + for (auto& codec_specific : lc3_codec_specifics) { + copy_codec_specific(codec_config.config, codec_specific); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc); + + ASSERT_TRUE(aidl_retval.isOk()); + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } +} + +/** + * Test whether each provider of type + * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with + * AptX hardware encoding config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + StartAndEndA2dpAptxDecodingHardwareSession) { + if (!IsOffloadSupported()) { + return; + } + + for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) { + CodecConfiguration codec_config = { + .codecType = codec_type, + .encodedAudioBitrate = + (codec_type == CodecType::APTX ? 352000 : 576000), + .peerMtu = 1005, + .isScmstEnabled = false, + }; + + auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList( + (codec_type == CodecType::APTX_HD ? true : false), true); + + for (auto& codec_specific : aptx_codec_specifics) { + copy_codec_specific(codec_config.config, codec_specific); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(codec_config), latency_modes, + &mq_desc); + + ASSERT_TRUE(aidl_retval.isOk()); + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } + } +} + +/** + * Test whether each provider of type + * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with + * an invalid codec config + */ +TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl, + StartAndEndA2dpDecodingHardwareSessionInvalidCodecConfig) { + if (!IsOffloadSupported()) { + return; + } + ASSERT_NE(audio_provider_, nullptr); + + std::vector codec_specifics; + for (auto codec_type : a2dp_codec_types) { + switch (codec_type) { + case CodecType::SBC: + codec_specifics = GetSbcCodecSpecificSupportedList(false); + break; + case CodecType::AAC: + codec_specifics = GetAacCodecSpecificSupportedList(false); + break; + case CodecType::LDAC: + codec_specifics = GetLdacCodecSpecificSupportedList(false); + break; + case CodecType::APTX: + codec_specifics = GetAptxCodecSpecificSupportedList(false, false); + break; + case CodecType::APTX_HD: + codec_specifics = GetAptxCodecSpecificSupportedList(true, false); + break; + case CodecType::LC3: + codec_specifics = GetLc3CodecSpecificSupportedList(false); + continue; + case CodecType::APTX_ADAPTIVE: + case CodecType::VENDOR: + case CodecType::UNKNOWN: + codec_specifics.clear(); + break; + } + if (codec_specifics.empty()) { + continue; + } + + CodecConfiguration codec_config = { + .codecType = codec_type, + .encodedAudioBitrate = 328000, + .peerMtu = 1005, + .isScmstEnabled = false, + }; + for (auto codec_specific : codec_specifics) { + copy_codec_specific(codec_config.config, codec_specific); + DataMQDesc mq_desc; + auto aidl_retval = audio_provider_->startSession( + audio_port_, AudioConfiguration(codec_config), latency_modes, + &mq_desc); + + // AIDL call should fail on invalid codec + ASSERT_FALSE(aidl_retval.isOk()); + EXPECT_TRUE(audio_provider_->endSession().isOk()); + } + } +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProviderFactoryAidl); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl, @@ -1596,15 +1922,17 @@ INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl, android::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( - BluetoothAudioProviderA2dpSoftwareAidl); -INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareAidl, + BluetoothAudioProviderA2dpEncodingSoftwareAidl); +INSTANTIATE_TEST_SUITE_P(PerInstance, + BluetoothAudioProviderA2dpEncodingSoftwareAidl, testing::ValuesIn(android::getAidlHalInstanceNames( IBluetoothAudioProviderFactory::descriptor)), android::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( - BluetoothAudioProviderA2dpHardwareAidl); -INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareAidl, + BluetoothAudioProviderA2dpEncodingHardwareAidl); +INSTANTIATE_TEST_SUITE_P(PerInstance, + BluetoothAudioProviderA2dpEncodingHardwareAidl, testing::ValuesIn(android::getAidlHalInstanceNames( IBluetoothAudioProviderFactory::descriptor)), android::PrintInstanceNameToString); @@ -1665,6 +1993,22 @@ INSTANTIATE_TEST_SUITE_P(PerInstance, IBluetoothAudioProviderFactory::descriptor)), android::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + BluetoothAudioProviderA2dpDecodingSoftwareAidl); +INSTANTIATE_TEST_SUITE_P(PerInstance, + BluetoothAudioProviderA2dpDecodingSoftwareAidl, + testing::ValuesIn(android::getAidlHalInstanceNames( + IBluetoothAudioProviderFactory::descriptor)), + android::PrintInstanceNameToString); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( + BluetoothAudioProviderA2dpDecodingHardwareAidl); +INSTANTIATE_TEST_SUITE_P(PerInstance, + BluetoothAudioProviderA2dpDecodingHardwareAidl, + testing::ValuesIn(android::getAidlHalInstanceNames( + IBluetoothAudioProviderFactory::descriptor)), + android::PrintInstanceNameToString); + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ABinderProcess_setThreadPoolMaxThreadCount(1); diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp index 8fd1ab5cae..fc54c70158 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp @@ -323,7 +323,8 @@ BluetoothAudioCodecs::GetSoftwarePcmCapabilities() { std::vector BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities( const SessionType& session_type) { - if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH && + session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { return {}; } std::vector offload_a2dp_codec_capabilities = @@ -389,7 +390,8 @@ bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid( bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid( const SessionType& session_type, const CodecConfiguration& codec_config) { - if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH && + session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { LOG(ERROR) << __func__ << ": Invalid SessionType=" << toString(session_type); return false; diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp index cdee520b11..3214bf2228 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp @@ -92,6 +92,7 @@ const AudioConfiguration BluetoothAudioSession::GetAudioConfig() { if (!IsSessionReady()) { switch (session_type_) { case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: return AudioConfiguration(CodecConfiguration{}); case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH: case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH: @@ -143,6 +144,7 @@ bool BluetoothAudioSession::IsSessionReady() { SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || session_type_ == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH || (data_mq_ != nullptr && data_mq_->isValid())); return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr; } @@ -267,9 +269,11 @@ bool BluetoothAudioSession::UpdateAudioConfig( session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH || session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH || session_type_ == - SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH); + SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH); bool is_offload_a2dp_session = - (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); + (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH); bool is_offload_le_audio_session = (session_type_ == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || @@ -468,7 +472,9 @@ void BluetoothAudioSession::UpdateSourceMetadata( LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << "," << track_count << " track(s)"; if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH || + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { return; } @@ -509,7 +515,9 @@ void BluetoothAudioSession::UpdateSinkMetadata( LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << "," << track_count << " track(s)"; if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH || + session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH || + session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) { return; } diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h index 5b838b0b3f..0782c824e1 100644 --- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h +++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h @@ -82,6 +82,7 @@ class BluetoothAudioSessionControl { } switch (session_type) { case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: + case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: return AudioConfiguration(CodecConfiguration{}); case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH: case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH: