/* * Copyright 2020 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. */ #define LOG_TAG "bluetooth_audio_hidl_hal_test" #include <VtsHalHidlTargetCallbackBase.h> #include <android-base/logging.h> #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h> #include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvider.h> #include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h> #include <fmq/MessageQueue.h> #include <gtest/gtest.h> #include <hidl/GtestPrinter.h> #include <hidl/MQDescriptor.h> #include <hidl/ServiceManagement.h> #include <utils/Log.h> using ::android::sp; using ::android::hardware::hidl_vec; using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::MessageQueue; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::audio::common::V5_0::SourceMetadata; using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; using ::android::hardware::bluetooth::audio::V2_0::AacParameters; using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate; using ::android::hardware::bluetooth::audio::V2_0::AptxParameters; using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities; using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities; using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; using ::android::hardware::bluetooth::audio::V2_0::CodecType; using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort; using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider; using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode; using ::android::hardware::bluetooth::audio::V2_0::LdacParameters; using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex; using ::android::hardware::bluetooth::audio::V2_0::PcmParameters; using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod; using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength; using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode; using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands; using ::android::hardware::bluetooth::audio::V2_0::SbcParameters; using ::android::hardware::bluetooth::audio::V2_0::SessionType; using ::android::hardware::bluetooth::audio::V2_1:: IBluetoothAudioProvidersFactory; using ::android::hardware::bluetooth::audio::V2_1::SampleRate; using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>; using BluetoothAudioStatus = ::android::hardware::bluetooth::audio::V2_0::Status; using CodecSpecificConfig = ::android::hardware::bluetooth::audio::V2_0:: CodecConfiguration::CodecSpecific; namespace { constexpr android::hardware::bluetooth::audio::V2_0::SampleRate a2dp_sample_rates[5] = { android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_UNKNOWN, android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100, android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000, android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200, android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000}; constexpr BitsPerSample a2dp_bits_per_samples[4] = { BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24, BitsPerSample::BITS_32}; constexpr ChannelMode a2dp_channel_modes[3] = { ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO}; constexpr CodecType a2dp_codec_types[6] = {CodecType::UNKNOWN, CodecType::SBC, CodecType::AAC, CodecType::APTX, CodecType::APTX_HD, CodecType::LDAC}; template <typename T> std::vector<T> ExtractValuesFromBitmask(T bitmasks, uint32_t bitfield, bool supported) { std::vector<T> retval; if (!supported) { retval.push_back(static_cast<T>(bitfield)); } uint32_t test_bit = 0x00000001; while (test_bit <= static_cast<uint32_t>(bitmasks) && test_bit <= bitfield) { if ((bitfield & test_bit)) { if ((!(bitmasks & test_bit) && !supported) || ((bitmasks & test_bit) && supported)) { retval.push_back(static_cast<T>(test_bit)); } } if (test_bit == 0x80000000) { break; } test_bit <<= 1; } return retval; } } // namespace // The base test class for Bluetooth Audio HAL. class BluetoothAudioProvidersFactoryHidlTest : public ::testing::TestWithParam<std::string> { public: virtual void SetUp() override { providers_factory_ = IBluetoothAudioProvidersFactory::getService(GetParam()); ASSERT_NE(providers_factory_, nullptr); } virtual void TearDown() override { providers_factory_ = nullptr; } // A simple test implementation of IBluetoothAudioPort. class BluetoothAudioPort : public ::testing::VtsHalHidlTargetCallbackBase< BluetoothAudioProvidersFactoryHidlTest>, public IBluetoothAudioPort { BluetoothAudioProvidersFactoryHidlTest& parent_; public: BluetoothAudioPort(BluetoothAudioProvidersFactoryHidlTest& parent) : parent_(parent) {} virtual ~BluetoothAudioPort() = default; Return<void> startStream() override { parent_.audio_provider_->streamStarted(BluetoothAudioStatus::SUCCESS); return Void(); } Return<void> suspendStream() override { parent_.audio_provider_->streamSuspended(BluetoothAudioStatus::SUCCESS); return Void(); } Return<void> stopStream() override { return Void(); } Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) { _hidl_cb(BluetoothAudioStatus::SUCCESS, 0, 0, {.tvSec = 0, .tvNSec = 0}); return Void(); } Return<void> updateMetadata(const SourceMetadata& sourceMetadata __unused) { return Void(); } }; void GetProviderCapabilitiesHelper(const SessionType& session_type) { temp_provider_capabilities_.clear(); auto hidl_cb = [&temp_capabilities = this->temp_provider_capabilities_]( const hidl_vec<AudioCapabilities>& audioCapabilities) { for (auto audioCapability : audioCapabilities) temp_capabilities.push_back(audioCapability); }; auto hidl_retval = providers_factory_->getProviderCapabilities(session_type, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (session_type == SessionType::UNKNOWN) { ASSERT_TRUE(temp_provider_capabilities_.empty()); } else if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { // All software paths are mandatory and must have exact 1 "PcmParameters" ASSERT_EQ(temp_provider_capabilities_.size(), 1); ASSERT_EQ(temp_provider_capabilities_[0].getDiscriminator(), AudioCapabilities::hidl_discriminator::pcmCapabilities); } else { uint32_t codec_type_bitmask = 0x00000000; // empty capability means offload is unsupported for (auto audio_capability : temp_provider_capabilities_) { ASSERT_EQ(audio_capability.getDiscriminator(), AudioCapabilities::hidl_discriminator::codecCapabilities); const CodecCapabilities& codec_capabilities = audio_capability.codecCapabilities(); // Every codec can present once at most ASSERT_EQ(codec_type_bitmask & static_cast<uint32_t>(codec_capabilities.codecType), 0); switch (codec_capabilities.codecType) { case CodecType::SBC: ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), CodecCapabilities::Capabilities::hidl_discriminator:: sbcCapabilities); break; case CodecType::AAC: ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), CodecCapabilities::Capabilities::hidl_discriminator:: aacCapabilities); break; case CodecType::APTX: FALLTHROUGH_INTENDED; case CodecType::APTX_HD: ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), CodecCapabilities::Capabilities::hidl_discriminator:: aptxCapabilities); break; case CodecType::LDAC: ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), CodecCapabilities::Capabilities::hidl_discriminator:: ldacCapabilities); break; case CodecType::UNKNOWN: break; } codec_type_bitmask |= codec_capabilities.codecType; } } } void GetProviderCapabilitiesHelper_2_1( const android::hardware::bluetooth::audio::V2_1::SessionType& session_type) { temp_provider_capabilities_2_1_.clear(); auto hidl_cb = [&temp_capabilities = this->temp_provider_capabilities_2_1_]( const hidl_vec< android::hardware::bluetooth::audio::V2_1::AudioCapabilities>& audioCapabilities) { for (auto audioCapability : audioCapabilities) temp_capabilities.push_back(audioCapability); }; auto hidl_retval = providers_factory_->getProviderCapabilities_2_1(session_type, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); // All software paths are mandatory and must have exact 1 "PcmParameters" ASSERT_EQ(temp_provider_capabilities_2_1_.size(), 1); ASSERT_EQ(temp_provider_capabilities_2_1_[0].getDiscriminator(), android::hardware::bluetooth::audio::V2_1::AudioCapabilities:: hidl_discriminator::pcmCapabilities); } // This helps to open the specified provider and check the openProvider() // has corruct return values. BUT, to keep it simple, it does not consider // the capability, and please do so at the SetUp of each session's test. void OpenProviderHelper(const SessionType& session_type) { BluetoothAudioStatus cb_status; auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_]( BluetoothAudioStatus status, const sp<IBluetoothAudioProvider>& provider) { cb_status = status; local_provider = provider; }; auto hidl_retval = providers_factory_->openProvider(session_type, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (cb_status == BluetoothAudioStatus::SUCCESS) { ASSERT_NE(session_type, SessionType::UNKNOWN); ASSERT_NE(audio_provider_, nullptr); audio_port_ = new BluetoothAudioPort(*this); } else { // A2DP_HARDWARE_OFFLOAD_DATAPATH is optional ASSERT_TRUE(session_type == SessionType::UNKNOWN || session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE); ASSERT_EQ(audio_provider_, nullptr); } } // This helps to open the specified provider and check the openProvider_2_1() // has corruct return values. BUT, to keep it simple, it does not consider // the capability, and please do so at the SetUp of each session's test. void OpenProviderHelper_2_1( const android::hardware::bluetooth::audio::V2_1::SessionType& session_type) { BluetoothAudioStatus cb_status; auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_2_1_]( BluetoothAudioStatus status, const sp<android::hardware::bluetooth::audio::V2_1:: IBluetoothAudioProvider>& provider) { cb_status = status; local_provider = provider; }; auto hidl_retval = providers_factory_->openProvider_2_1(session_type, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (cb_status == BluetoothAudioStatus::SUCCESS) { ASSERT_NE( session_type, android::hardware::bluetooth::audio::V2_1::SessionType::UNKNOWN); ASSERT_NE(audio_provider_2_1_, nullptr); audio_port_ = new BluetoothAudioPort(*this); } else { ASSERT_TRUE( session_type == android::hardware::bluetooth::audio::V2_1::SessionType::UNKNOWN); ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE); ASSERT_EQ(audio_provider_2_1_, nullptr); } } bool IsPcmParametersSupported(const PcmParameters& pcm_parameters) { if (temp_provider_capabilities_.size() != 1 || temp_provider_capabilities_[0].getDiscriminator() != AudioCapabilities::hidl_discriminator::pcmCapabilities) { return false; } auto pcm_capability = temp_provider_capabilities_[0].pcmCapabilities(); bool is_parameter_valid = (pcm_parameters.sampleRate != android::hardware::bluetooth::audio:: V2_0::SampleRate::RATE_UNKNOWN && pcm_parameters.channelMode != ChannelMode::UNKNOWN && pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN); bool is_parameter_in_capability = (pcm_capability.sampleRate & pcm_parameters.sampleRate && pcm_capability.channelMode & pcm_parameters.channelMode && pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample); return is_parameter_valid && is_parameter_in_capability; } bool IsPcmParametersSupported_2_1( const android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_parameters) { if (temp_provider_capabilities_2_1_.size() != 1 || temp_provider_capabilities_2_1_[0].getDiscriminator() != android::hardware::bluetooth::audio::V2_1::AudioCapabilities:: hidl_discriminator::pcmCapabilities) { return false; } auto pcm_capability = temp_provider_capabilities_2_1_[0].pcmCapabilities(); bool is_parameter_valid = (pcm_parameters.sampleRate != SampleRate::RATE_UNKNOWN && pcm_parameters.channelMode != ChannelMode::UNKNOWN && pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN && pcm_parameters.dataIntervalUs != 0); bool is_parameter_in_capability = (pcm_capability.sampleRate & pcm_parameters.sampleRate && pcm_capability.channelMode & pcm_parameters.channelMode && pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample); return is_parameter_valid && is_parameter_in_capability; } sp<IBluetoothAudioProvidersFactory> providers_factory_; // temp storage saves the specified provider capability by // GetProviderCapabilitiesHelper() std::vector<AudioCapabilities> temp_provider_capabilities_; std::vector<android::hardware::bluetooth::audio::V2_1::AudioCapabilities> temp_provider_capabilities_2_1_; // audio_provider_ is for the Bluetooth stack to report session started/ended // and handled audio stream started / suspended sp<IBluetoothAudioProvider> audio_provider_; sp<android::hardware::bluetooth::audio::V2_1::IBluetoothAudioProvider> audio_provider_2_1_; // audio_port_ is for the Audio HAL to send stream start/suspend/stop commands // to Bluetooth stack sp<IBluetoothAudioPort> audio_port_; static constexpr SessionType session_types_[4] = { SessionType::UNKNOWN, SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH, SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH, SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH}; }; /** * Test whether we can get the FactoryService from HIDL */ TEST_P(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {} /** * Test whether we can open a provider for each provider returned by * getProviderCapabilities() with non-empty capabalities */ TEST_P(BluetoothAudioProvidersFactoryHidlTest, OpenProviderAndCheckCapabilitiesBySession) { for (auto session_type : session_types_) { 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 BluetoothAudioProviderA2dpSoftwareHidlTest : public BluetoothAudioProvidersFactoryHidlTest { public: virtual void SetUp() override { BluetoothAudioProvidersFactoryHidlTest::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; BluetoothAudioProvidersFactoryHidlTest::TearDown(); } }; /** * Test whether we can open a provider of type */ TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {} /** * Test whether each provider of type * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with * different PCM config */ TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest, StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) { bool is_codec_config_valid; std::unique_ptr<DataMQ> tempDataMQ; auto hidl_cb = [&is_codec_config_valid, &tempDataMQ]( BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { if (is_codec_config_valid) { ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS); ASSERT_TRUE(dataMQ.isHandleValid()); tempDataMQ.reset(new DataMQ(dataMQ)); } else { EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); EXPECT_FALSE(dataMQ.isHandleValid()); } }; AudioConfiguration audio_config = {}; PcmParameters pcm_parameters = {}; for (auto sample_rate : a2dp_sample_rates) { pcm_parameters.sampleRate = sample_rate; for (auto bits_per_sample : a2dp_bits_per_samples) { pcm_parameters.bitsPerSample = bits_per_sample; for (auto channel_mode : a2dp_channel_modes) { pcm_parameters.channelMode = channel_mode; is_codec_config_valid = IsPcmParametersSupported(pcm_parameters); audio_config.pcmConfig(pcm_parameters); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (is_codec_config_valid) { EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid()); } EXPECT_TRUE(audio_provider_->endSession().isOk()); } // ChannelMode } // BitsPerSampple } // SampleRate } /** * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH */ class BluetoothAudioProviderA2dpHardwareHidlTest : public BluetoothAudioProvidersFactoryHidlTest { public: virtual void SetUp() override { BluetoothAudioProvidersFactoryHidlTest::SetUp(); GetProviderCapabilitiesHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); ASSERT_TRUE(temp_provider_capabilities_.empty() || audio_provider_ != nullptr); } virtual void TearDown() override { audio_port_ = nullptr; audio_provider_ = nullptr; BluetoothAudioProvidersFactoryHidlTest::TearDown(); } bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); } void GetOffloadCodecCapabilityHelper(const CodecType& codec_type) { temp_codec_capabilities_ = {}; for (auto codec_capability : temp_provider_capabilities_) { if (codec_capability.codecCapabilities().codecType != codec_type) { continue; } temp_codec_capabilities_ = codec_capability.codecCapabilities(); } } std::vector<CodecSpecificConfig> GetSbcCodecSpecificSupportedList( bool supported) { std::vector<CodecSpecificConfig> sbc_codec_specifics; GetOffloadCodecCapabilityHelper(CodecType::SBC); if (temp_codec_capabilities_.codecType != CodecType::SBC) { return sbc_codec_specifics; } // parse the capability SbcParameters sbc_capability = temp_codec_capabilities_.capabilities.sbcCapabilities(); if (sbc_capability.minBitpool > sbc_capability.maxBitpool) { return sbc_codec_specifics; } std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate> sample_rates = ExtractValuesFromBitmask< android::hardware::bluetooth::audio::V2_0::SampleRate>( sbc_capability.sampleRate, 0xff, supported); std::vector<SbcChannelMode> channel_modes = ExtractValuesFromBitmask<SbcChannelMode>(sbc_capability.channelMode, 0x0f, supported); std::vector<SbcBlockLength> block_lengths = ExtractValuesFromBitmask<SbcBlockLength>(sbc_capability.blockLength, 0xf0, supported); std::vector<SbcNumSubbands> num_subbandss = ExtractValuesFromBitmask<SbcNumSubbands>(sbc_capability.numSubbands, 0x0c, supported); std::vector<SbcAllocMethod> alloc_methods = ExtractValuesFromBitmask<SbcAllocMethod>(sbc_capability.allocMethod, 0x03, supported); std::vector<BitsPerSample> bits_per_samples = ExtractValuesFromBitmask<BitsPerSample>(sbc_capability.bitsPerSample, 0x07, supported); // combine those parameters into one list of // CodecConfiguration::CodecSpecific CodecSpecificConfig codec_specific = {}; SbcParameters sbc_data; for (auto sample_rate : sample_rates) { for (auto channel_mode : channel_modes) { for (auto block_length : block_lengths) { for (auto num_subbands : num_subbandss) { for (auto alloc_method : alloc_methods) { for (auto bits_per_sample : bits_per_samples) { sbc_data = {.sampleRate = sample_rate, .channelMode = channel_mode, .blockLength = block_length, .numSubbands = num_subbands, .allocMethod = alloc_method, .bitsPerSample = bits_per_sample, .minBitpool = sbc_capability.minBitpool, .maxBitpool = sbc_capability.maxBitpool}; codec_specific.sbcConfig(sbc_data); sbc_codec_specifics.push_back(codec_specific); } } } } } } return sbc_codec_specifics; } std::vector<CodecSpecificConfig> GetAacCodecSpecificSupportedList( bool supported) { std::vector<CodecSpecificConfig> aac_codec_specifics; GetOffloadCodecCapabilityHelper(CodecType::AAC); if (temp_codec_capabilities_.codecType != CodecType::AAC) { return aac_codec_specifics; } // parse the capability AacParameters aac_capability = temp_codec_capabilities_.capabilities.aacCapabilities(); std::vector<AacObjectType> object_types = ExtractValuesFromBitmask<AacObjectType>(aac_capability.objectType, 0xf0, supported); std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate> sample_rates = ExtractValuesFromBitmask< android::hardware::bluetooth::audio::V2_0::SampleRate>( aac_capability.sampleRate, 0xff, supported); std::vector<ChannelMode> channel_modes = ExtractValuesFromBitmask<ChannelMode>(aac_capability.channelMode, 0x03, supported); std::vector<AacVariableBitRate> variable_bit_rate_enableds = { AacVariableBitRate::DISABLED}; if (aac_capability.variableBitRateEnabled == AacVariableBitRate::ENABLED) { variable_bit_rate_enableds.push_back(AacVariableBitRate::ENABLED); } std::vector<BitsPerSample> bits_per_samples = ExtractValuesFromBitmask<BitsPerSample>(aac_capability.bitsPerSample, 0x07, supported); // combine those parameters into one list of // CodecConfiguration::CodecSpecific CodecSpecificConfig codec_specific = {}; AacParameters aac_data; for (auto object_type : object_types) { for (auto sample_rate : sample_rates) { for (auto channel_mode : channel_modes) { for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) { for (auto bits_per_sample : bits_per_samples) { aac_data = {.objectType = object_type, .sampleRate = sample_rate, .channelMode = channel_mode, .variableBitRateEnabled = variable_bit_rate_enabled, .bitsPerSample = bits_per_sample}; codec_specific.aacConfig(aac_data); aac_codec_specifics.push_back(codec_specific); } } } } } return aac_codec_specifics; } std::vector<CodecSpecificConfig> GetLdacCodecSpecificSupportedList( bool supported) { std::vector<CodecSpecificConfig> ldac_codec_specifics; GetOffloadCodecCapabilityHelper(CodecType::LDAC); if (temp_codec_capabilities_.codecType != CodecType::LDAC) { return ldac_codec_specifics; } // parse the capability LdacParameters ldac_capability = temp_codec_capabilities_.capabilities.ldacCapabilities(); std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate> sample_rates = ExtractValuesFromBitmask< android::hardware::bluetooth::audio::V2_0::SampleRate>( ldac_capability.sampleRate, 0xff, supported); std::vector<LdacChannelMode> channel_modes = ExtractValuesFromBitmask<LdacChannelMode>(ldac_capability.channelMode, 0x07, supported); std::vector<LdacQualityIndex> quality_indexes = { LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID, LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR}; std::vector<BitsPerSample> bits_per_samples = ExtractValuesFromBitmask<BitsPerSample>(ldac_capability.bitsPerSample, 0x07, supported); // combine those parameters into one list of // CodecConfiguration::CodecSpecific CodecSpecificConfig codec_specific = {}; LdacParameters ldac_data; for (auto sample_rate : sample_rates) { for (auto channel_mode : channel_modes) { for (auto quality_index : quality_indexes) { for (auto bits_per_sample : bits_per_samples) { ldac_data = {.sampleRate = sample_rate, .channelMode = channel_mode, .qualityIndex = quality_index, .bitsPerSample = bits_per_sample}; codec_specific.ldacConfig(ldac_data); ldac_codec_specifics.push_back(codec_specific); } } } } return ldac_codec_specifics; } std::vector<CodecSpecificConfig> GetAptxCodecSpecificSupportedList( bool is_hd, bool supported) { std::vector<CodecSpecificConfig> aptx_codec_specifics; GetOffloadCodecCapabilityHelper( (is_hd ? CodecType::APTX_HD : CodecType::APTX)); if ((is_hd && temp_codec_capabilities_.codecType != CodecType::APTX_HD) || (!is_hd && temp_codec_capabilities_.codecType != CodecType::APTX)) { return aptx_codec_specifics; } // parse the capability AptxParameters aptx_capability = temp_codec_capabilities_.capabilities.aptxCapabilities(); std::vector<android::hardware::bluetooth::audio::V2_0::SampleRate> sample_rates = ExtractValuesFromBitmask< android::hardware::bluetooth::audio::V2_0::SampleRate>( aptx_capability.sampleRate, 0xff, supported); std::vector<ChannelMode> channel_modes = ExtractValuesFromBitmask<ChannelMode>(aptx_capability.channelMode, 0x03, supported); std::vector<BitsPerSample> bits_per_samples = ExtractValuesFromBitmask<BitsPerSample>(aptx_capability.bitsPerSample, 0x07, supported); // combine those parameters into one list of // CodecConfiguration::CodecSpecific CodecSpecificConfig codec_specific = {}; AptxParameters aptx_data; for (auto sample_rate : sample_rates) { for (auto channel_mode : channel_modes) { for (auto bits_per_sample : bits_per_samples) { aptx_data = {.sampleRate = sample_rate, .channelMode = channel_mode, .bitsPerSample = bits_per_sample}; codec_specific.aptxConfig(aptx_data); aptx_codec_specifics.push_back(codec_specific); } } } return aptx_codec_specifics; } // temp storage saves the specified codec capability by // GetOffloadCodecCapabilityHelper() CodecCapabilities temp_codec_capabilities_; }; /** * Test whether we can open a provider of type */ TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {} /** * Test whether each provider of type * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * SBC hardware encoding config */ TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, StartAndEndA2dpSbcHardwareSession) { if (!IsOffloadSupported()) { return; } CodecConfiguration codec_config = {}; codec_config.codecType = CodecType::SBC; codec_config.encodedAudioBitrate = 328000; codec_config.peerMtu = 1005; codec_config.isScmstEnabled = false; AudioConfiguration audio_config = {}; std::vector<CodecSpecificConfig> sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true); auto hidl_cb = [](BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); EXPECT_FALSE(dataMQ.isHandleValid()); }; for (auto codec_specific : sbc_codec_specifics) { codec_config.config = codec_specific; audio_config.codecConfig(codec_config); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); EXPECT_TRUE(audio_provider_->endSession().isOk()); } } /** * Test whether each provider of type * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * AAC hardware encoding config */ TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, StartAndEndA2dpAacHardwareSession) { if (!IsOffloadSupported()) { return; } CodecConfiguration codec_config = {}; codec_config.codecType = CodecType::AAC; codec_config.encodedAudioBitrate = 320000; codec_config.peerMtu = 1005; codec_config.isScmstEnabled = false; AudioConfiguration audio_config = {}; std::vector<CodecSpecificConfig> aac_codec_specifics = GetAacCodecSpecificSupportedList(true); auto hidl_cb = [](BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); EXPECT_FALSE(dataMQ.isHandleValid()); }; for (auto codec_specific : aac_codec_specifics) { codec_config.config = codec_specific; audio_config.codecConfig(codec_config); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); EXPECT_TRUE(audio_provider_->endSession().isOk()); } } /** * Test whether each provider of type * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * LDAC hardware encoding config */ TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, StartAndEndA2dpLdacHardwareSession) { if (!IsOffloadSupported()) { return; } CodecConfiguration codec_config = {}; codec_config.codecType = CodecType::LDAC; codec_config.encodedAudioBitrate = 990000; codec_config.peerMtu = 1005; codec_config.isScmstEnabled = false; AudioConfiguration audio_config = {}; std::vector<CodecSpecificConfig> ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true); auto hidl_cb = [](BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); EXPECT_FALSE(dataMQ.isHandleValid()); }; for (auto codec_specific : ldac_codec_specifics) { codec_config.config = codec_specific; audio_config.codecConfig(codec_config); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); EXPECT_TRUE(audio_provider_->endSession().isOk()); } } /** * Test whether each provider of type * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * AptX hardware encoding config */ TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, StartAndEndA2dpAptxHardwareSession) { if (!IsOffloadSupported()) { return; } for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) { CodecConfiguration codec_config = {}; codec_config.codecType = codec_type; codec_config.encodedAudioBitrate = (codec_type == CodecType::APTX ? 352000 : 576000); codec_config.peerMtu = 1005; codec_config.isScmstEnabled = false; AudioConfiguration audio_config = {}; std::vector<CodecSpecificConfig> aptx_codec_specifics = GetAptxCodecSpecificSupportedList( (codec_type == CodecType::APTX_HD ? true : false), true); auto hidl_cb = [](BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); EXPECT_FALSE(dataMQ.isHandleValid()); }; for (auto codec_specific : aptx_codec_specifics) { codec_config.config = codec_specific; audio_config.codecConfig(codec_config); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); EXPECT_TRUE(audio_provider_->endSession().isOk()); } } } /** * Test whether each provider of type * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with * an invalid codec config */ TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, StartAndEndA2dpHardwareSessionInvalidCodecConfig) { if (!IsOffloadSupported()) { return; } ASSERT_NE(audio_provider_, nullptr); std::vector<CodecSpecificConfig> 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::UNKNOWN: codec_specifics.clear(); break; } if (codec_specifics.empty()) { continue; } CodecConfiguration codec_config = {}; codec_config.codecType = codec_type; codec_config.encodedAudioBitrate = 328000; codec_config.peerMtu = 1005; codec_config.isScmstEnabled = false; AudioConfiguration audio_config = {}; auto hidl_cb = [](BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); EXPECT_FALSE(dataMQ.isHandleValid()); }; for (auto codec_specific : codec_specifics) { codec_config.config = codec_specific; audio_config.codecConfig(codec_config); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); EXPECT_TRUE(audio_provider_->endSession().isOk()); } } } /** * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH */ class BluetoothAudioProviderHearingAidSoftwareHidlTest : public BluetoothAudioProvidersFactoryHidlTest { public: virtual void SetUp() override { BluetoothAudioProvidersFactoryHidlTest::SetUp(); GetProviderCapabilitiesHelper( SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH); OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH); ASSERT_NE(audio_provider_, nullptr); } virtual void TearDown() override { audio_port_ = nullptr; audio_provider_ = nullptr; BluetoothAudioProvidersFactoryHidlTest::TearDown(); } static constexpr android::hardware::bluetooth::audio::V2_0::SampleRate hearing_aid_sample_rates_[3] = { android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_UNKNOWN, android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000, android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000}; static constexpr BitsPerSample hearing_aid_bits_per_samples_[3] = { BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24}; static constexpr ChannelMode hearing_aid_channel_modes_[3] = { ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO}; }; /** * Test whether each provider of type * SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and * stopped with SBC hardware encoding config */ TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest, OpenHearingAidSoftwareProvider) {} /** * Test whether each provider of type * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and * stopped with different PCM config */ TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest, StartAndEndHearingAidSessionWithPossiblePcmConfig) { bool is_codec_config_valid; std::unique_ptr<DataMQ> tempDataMQ; auto hidl_cb = [&is_codec_config_valid, &tempDataMQ]( BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { if (is_codec_config_valid) { ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS); ASSERT_TRUE(dataMQ.isHandleValid()); tempDataMQ.reset(new DataMQ(dataMQ)); } else { EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); EXPECT_FALSE(dataMQ.isHandleValid()); } }; AudioConfiguration audio_config = {}; PcmParameters pcm_parameters = {}; for (auto sample_rate : hearing_aid_sample_rates_) { pcm_parameters.sampleRate = sample_rate; for (auto bits_per_sample : hearing_aid_bits_per_samples_) { pcm_parameters.bitsPerSample = bits_per_sample; for (auto channel_mode : hearing_aid_channel_modes_) { pcm_parameters.channelMode = channel_mode; is_codec_config_valid = IsPcmParametersSupported(pcm_parameters); audio_config.pcmConfig(pcm_parameters); auto hidl_retval = audio_provider_->startSession(audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (is_codec_config_valid) { EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid()); } EXPECT_TRUE(audio_provider_->endSession().isOk()); } // ChannelMode } // BitsPerSampple } // SampleRate } /** * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH */ class BluetoothAudioProviderLeAudioOutputSoftwareHidlTest : public BluetoothAudioProvidersFactoryHidlTest { public: virtual void SetUp() override { BluetoothAudioProvidersFactoryHidlTest::SetUp(); GetProviderCapabilitiesHelper_2_1( android::hardware::bluetooth::audio::V2_1::SessionType:: LE_AUDIO_SOFTWARE_ENCODING_DATAPATH); OpenProviderHelper_2_1( android::hardware::bluetooth::audio::V2_1::SessionType:: LE_AUDIO_SOFTWARE_ENCODING_DATAPATH); ASSERT_NE(audio_provider_2_1_, nullptr); } virtual void TearDown() override { audio_port_ = nullptr; audio_provider_2_1_ = nullptr; BluetoothAudioProvidersFactoryHidlTest::TearDown(); } static constexpr SampleRate le_audio_output_sample_rates_[11] = { SampleRate::RATE_UNKNOWN, SampleRate::RATE_8000, SampleRate::RATE_16000, SampleRate::RATE_24000, SampleRate::RATE_32000, SampleRate::RATE_44100, SampleRate::RATE_48000}; static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = { BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24}; static constexpr ChannelMode le_audio_output_channel_modes_[3] = { ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO}; static constexpr uint32_t le_audio_output_data_interval_us_[2] = { 0 /* Invalid */, 10000 /* Valid 10ms */}; }; /** * Test whether each provider of type * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and * stopped */ TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareHidlTest, OpenLeAudioOutputSoftwareProvider) {} /** * Test whether each provider of type * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and * stopped with different PCM config */ TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareHidlTest, DISABLED_StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) { bool is_codec_config_valid; std::unique_ptr<DataMQ> tempDataMQ; auto hidl_cb = [&is_codec_config_valid, &tempDataMQ]( BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { if (is_codec_config_valid) { ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS); ASSERT_TRUE(dataMQ.isHandleValid()); tempDataMQ.reset(new DataMQ(dataMQ)); } else { EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); EXPECT_FALSE(dataMQ.isHandleValid()); tempDataMQ.reset(nullptr); } }; android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config = {}; android::hardware::bluetooth::audio::V2_1::PcmParameters pcm_parameters = {}; for (auto sample_rate : le_audio_output_sample_rates_) { pcm_parameters.sampleRate = sample_rate; for (auto bits_per_sample : le_audio_output_bits_per_samples_) { pcm_parameters.bitsPerSample = bits_per_sample; for (auto channel_mode : le_audio_output_channel_modes_) { pcm_parameters.channelMode = channel_mode; for (auto data_interval_us : le_audio_output_data_interval_us_) { pcm_parameters.dataIntervalUs = data_interval_us; is_codec_config_valid = IsPcmParametersSupported_2_1(pcm_parameters); audio_config.pcmConfig(pcm_parameters); auto hidl_retval = audio_provider_2_1_->startSession_2_1( audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (is_codec_config_valid) { EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid()); } else { EXPECT_TRUE(tempDataMQ == nullptr); } EXPECT_TRUE(audio_provider_2_1_->endSession().isOk()); } // uint32_t (data interval in microseconds) } // ChannelMode } // BitsPerSampple } // SampleRate } /** * openProvider LE_AUDIO_SOFTWARE_DECODED_DATAPATH */ class BluetoothAudioProviderLeAudioInputSoftwareHidlTest : public BluetoothAudioProvidersFactoryHidlTest { public: virtual void SetUp() override { BluetoothAudioProvidersFactoryHidlTest::SetUp(); GetProviderCapabilitiesHelper_2_1( android::hardware::bluetooth::audio::V2_1::SessionType:: LE_AUDIO_SOFTWARE_DECODED_DATAPATH); OpenProviderHelper_2_1(android::hardware::bluetooth::audio::V2_1:: SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH); ASSERT_NE(audio_provider_2_1_, nullptr); } virtual void TearDown() override { audio_port_ = nullptr; audio_provider_2_1_ = nullptr; BluetoothAudioProvidersFactoryHidlTest::TearDown(); } static constexpr SampleRate le_audio_output_sample_rates_[11] = { SampleRate::RATE_UNKNOWN, SampleRate::RATE_8000, SampleRate::RATE_16000, SampleRate::RATE_24000, SampleRate::RATE_32000, SampleRate::RATE_44100, SampleRate::RATE_48000}; static constexpr BitsPerSample le_audio_output_bits_per_samples_[3] = { BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24}; static constexpr ChannelMode le_audio_output_channel_modes_[3] = { ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO}; static constexpr uint32_t le_audio_output_data_interval_us_[2] = { 0 /* Invalid */, 10000 /* Valid 10ms */}; }; /** * Test whether each provider of type * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and * stopped */ TEST_P(BluetoothAudioProviderLeAudioInputSoftwareHidlTest, OpenLeAudioInputSoftwareProvider) {} /** * Test whether each provider of type * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and * stopped with different PCM config */ TEST_P(BluetoothAudioProviderLeAudioInputSoftwareHidlTest, DISABLED_StartAndEndLeAudioInputSessionWithPossiblePcmConfig) { bool is_codec_config_valid; std::unique_ptr<DataMQ> tempDataMQ; auto hidl_cb = [&is_codec_config_valid, &tempDataMQ]( BluetoothAudioStatus status, const DataMQ::Descriptor& dataMQ) { if (is_codec_config_valid) { ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS); ASSERT_TRUE(dataMQ.isHandleValid()); tempDataMQ.reset(new DataMQ(dataMQ)); } else { EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); EXPECT_FALSE(dataMQ.isHandleValid()); tempDataMQ.reset(nullptr); } }; android::hardware::bluetooth::audio::V2_1::AudioConfiguration audio_config = {}; android::hardware::bluetooth::audio::V2_1::PcmParameters pcm_parameters = {}; for (auto sample_rate : le_audio_output_sample_rates_) { pcm_parameters.sampleRate = sample_rate; for (auto bits_per_sample : le_audio_output_bits_per_samples_) { pcm_parameters.bitsPerSample = bits_per_sample; for (auto channel_mode : le_audio_output_channel_modes_) { pcm_parameters.channelMode = channel_mode; for (auto data_interval_us : le_audio_output_data_interval_us_) { pcm_parameters.dataIntervalUs = data_interval_us; is_codec_config_valid = IsPcmParametersSupported_2_1(pcm_parameters); audio_config.pcmConfig(pcm_parameters); auto hidl_retval = audio_provider_2_1_->startSession_2_1( audio_port_, audio_config, hidl_cb); // HIDL calls should not be failed and callback has to be executed ASSERT_TRUE(hidl_retval.isOk()); if (is_codec_config_valid) { EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid()); } else { EXPECT_TRUE(tempDataMQ == nullptr); } EXPECT_TRUE(audio_provider_2_1_->endSession().isOk()); } // uint32_t (data interval in microseconds) } // ChannelMode } // BitsPerSampple } // SampleRate } static const std::vector<std::string> kAudioInstances = android::hardware::getAllHalInstanceNames( IBluetoothAudioProvidersFactory::descriptor); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProvidersFactoryHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProvidersFactoryHidlTest, testing::ValuesIn(kAudioInstances), android::hardware::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProviderA2dpSoftwareHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareHidlTest, testing::ValuesIn(kAudioInstances), android::hardware::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProviderA2dpHardwareHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareHidlTest, testing::ValuesIn(kAudioInstances), android::hardware::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProviderHearingAidSoftwareHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderHearingAidSoftwareHidlTest, testing::ValuesIn(kAudioInstances), android::hardware::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProviderLeAudioOutputSoftwareHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderLeAudioOutputSoftwareHidlTest, testing::ValuesIn(kAudioInstances), android::hardware::PrintInstanceNameToString); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( BluetoothAudioProviderLeAudioInputSoftwareHidlTest); INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderLeAudioInputSoftwareHidlTest, testing::ValuesIn(kAudioInstances), android::hardware::PrintInstanceNameToString);