1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "bluetooth_audio_hidl_hal_test" 18 19 #include <android-base/logging.h> 20 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h> 21 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h> 22 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h> 23 #include <fmq/MessageQueue.h> 24 #include <hidl/MQDescriptor.h> 25 #include <utils/Log.h> 26 27 #include <VtsHalHidlTargetCallbackBase.h> 28 #include <VtsHalHidlTargetTestBase.h> 29 #include <VtsHalHidlTargetTestEnvBase.h> 30 31 using ::android::sp; 32 using ::android::hardware::hidl_vec; 33 using ::android::hardware::kSynchronizedReadWrite; 34 using ::android::hardware::MessageQueue; 35 using ::android::hardware::Return; 36 using ::android::hardware::Void; 37 using ::android::hardware::audio::common::V5_0::SourceMetadata; 38 using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; 39 using ::android::hardware::bluetooth::audio::V2_0::AacParameters; 40 using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate; 41 using ::android::hardware::bluetooth::audio::V2_0::AptxParameters; 42 using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities; 43 using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; 44 using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; 45 using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; 46 using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities; 47 using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; 48 using ::android::hardware::bluetooth::audio::V2_0::CodecType; 49 using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort; 50 using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider; 51 using ::android::hardware::bluetooth::audio::V2_0:: 52 IBluetoothAudioProvidersFactory; 53 using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode; 54 using ::android::hardware::bluetooth::audio::V2_0::LdacParameters; 55 using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex; 56 using ::android::hardware::bluetooth::audio::V2_0::PcmParameters; 57 using ::android::hardware::bluetooth::audio::V2_0::SampleRate; 58 using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod; 59 using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength; 60 using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode; 61 using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands; 62 using ::android::hardware::bluetooth::audio::V2_0::SbcParameters; 63 using ::android::hardware::bluetooth::audio::V2_0::SessionType; 64 65 using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>; 66 using BluetoothAudioStatus = 67 ::android::hardware::bluetooth::audio::V2_0::Status; 68 using CodecSpecificConfig = ::android::hardware::bluetooth::audio::V2_0:: 69 CodecConfiguration::CodecSpecific; 70 71 namespace { 72 constexpr SampleRate a2dp_sample_rates[5] = { 73 SampleRate::RATE_UNKNOWN, SampleRate::RATE_44100, SampleRate::RATE_48000, 74 SampleRate::RATE_88200, SampleRate::RATE_96000}; 75 constexpr BitsPerSample a2dp_bits_per_samples[4] = { 76 BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24, 77 BitsPerSample::BITS_32}; 78 constexpr ChannelMode a2dp_channel_modes[3] = { 79 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO}; 80 constexpr CodecType a2dp_codec_types[6] = {CodecType::UNKNOWN, CodecType::SBC, 81 CodecType::AAC, CodecType::APTX, 82 CodecType::APTX_HD, CodecType::LDAC}; 83 84 template <typename T> 85 std::vector<T> ExtractValuesFromBitmask(T bitmasks, uint32_t bitfield, 86 bool supported) { 87 std::vector<T> retval; 88 if (!supported) { 89 retval.push_back(static_cast<T>(bitfield)); 90 } 91 uint32_t test_bit = 0x00000001; 92 while (test_bit <= static_cast<uint32_t>(bitmasks) && test_bit <= bitfield) { 93 if ((bitfield & test_bit)) { 94 if ((!(bitmasks & test_bit) && !supported) || 95 ((bitmasks & test_bit) && supported)) { 96 retval.push_back(static_cast<T>(test_bit)); 97 } 98 } 99 if (test_bit == 0x80000000) { 100 break; 101 } 102 test_bit <<= 1; 103 } 104 return retval; 105 } 106 } // namespace 107 108 // Test environment for Bluetooth Audio HAL. 109 class BluetoothAudioHidlEnvironment 110 : public ::testing::VtsHalHidlTargetTestEnvBase { 111 public: 112 // get the test environment singleton 113 static BluetoothAudioHidlEnvironment* Instance() { 114 static BluetoothAudioHidlEnvironment* instance = 115 new BluetoothAudioHidlEnvironment; 116 return instance; 117 } 118 119 virtual void registerTestServices() override { 120 registerTestService<IBluetoothAudioProvidersFactory>(); 121 } 122 123 private: 124 BluetoothAudioHidlEnvironment() {} 125 }; 126 127 // The base test class for Bluetooth Audio HAL. 128 class BluetoothAudioProvidersFactoryHidlTest 129 : public ::testing::VtsHalHidlTargetTestBase { 130 public: 131 virtual void SetUp() override { 132 providers_factory_ = ::testing::VtsHalHidlTargetTestBase::getService< 133 IBluetoothAudioProvidersFactory>( 134 BluetoothAudioHidlEnvironment::Instance() 135 ->getServiceName<IBluetoothAudioProvidersFactory>()); 136 ASSERT_NE(providers_factory_, nullptr); 137 } 138 139 virtual void TearDown() override { providers_factory_ = nullptr; } 140 141 // A simple test implementation of IBluetoothAudioPort. 142 class BluetoothAudioPort : public ::testing::VtsHalHidlTargetCallbackBase< 143 BluetoothAudioProvidersFactoryHidlTest>, 144 public IBluetoothAudioPort { 145 BluetoothAudioProvidersFactoryHidlTest& parent_; 146 147 public: 148 BluetoothAudioPort(BluetoothAudioProvidersFactoryHidlTest& parent) 149 : parent_(parent) {} 150 virtual ~BluetoothAudioPort() = default; 151 152 Return<void> startStream() override { 153 parent_.audio_provider_->streamStarted(BluetoothAudioStatus::SUCCESS); 154 return Void(); 155 } 156 157 Return<void> suspendStream() override { 158 parent_.audio_provider_->streamSuspended(BluetoothAudioStatus::SUCCESS); 159 return Void(); 160 } 161 162 Return<void> stopStream() override { return Void(); } 163 164 Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) { 165 _hidl_cb(BluetoothAudioStatus::SUCCESS, 0, 0, {.tvSec = 0, .tvNSec = 0}); 166 return Void(); 167 } 168 169 Return<void> updateMetadata(const SourceMetadata& sourceMetadata __unused) { 170 return Void(); 171 } 172 }; 173 174 void GetProviderCapabilitiesHelper(const SessionType& session_type) { 175 temp_provider_capabilities_.clear(); 176 auto hidl_cb = [& temp_capabilities = this->temp_provider_capabilities_]( 177 const hidl_vec<AudioCapabilities>& audioCapabilities) { 178 for (auto audioCapability : audioCapabilities) 179 temp_capabilities.push_back(audioCapability); 180 }; 181 auto hidl_retval = 182 providers_factory_->getProviderCapabilities(session_type, hidl_cb); 183 // HIDL calls should not be failed and callback has to be executed 184 ASSERT_TRUE(hidl_retval.isOk()); 185 if (session_type == SessionType::UNKNOWN) { 186 ASSERT_TRUE(temp_provider_capabilities_.empty()); 187 } else if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) { 188 // All software paths are mandatory and must have exact 1 "PcmParameters" 189 ASSERT_EQ(temp_provider_capabilities_.size(), 1); 190 ASSERT_EQ(temp_provider_capabilities_[0].getDiscriminator(), 191 AudioCapabilities::hidl_discriminator::pcmCapabilities); 192 } else { 193 uint32_t codec_type_bitmask = 0x00000000; 194 // empty capability means offload is unsupported 195 for (auto audio_capability : temp_provider_capabilities_) { 196 ASSERT_EQ(audio_capability.getDiscriminator(), 197 AudioCapabilities::hidl_discriminator::codecCapabilities); 198 const CodecCapabilities& codec_capabilities = 199 audio_capability.codecCapabilities(); 200 // Every codec can present once at most 201 ASSERT_EQ(codec_type_bitmask & 202 static_cast<uint32_t>(codec_capabilities.codecType), 203 0); 204 switch (codec_capabilities.codecType) { 205 case CodecType::SBC: 206 ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), 207 CodecCapabilities::Capabilities::hidl_discriminator:: 208 sbcCapabilities); 209 break; 210 case CodecType::AAC: 211 ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), 212 CodecCapabilities::Capabilities::hidl_discriminator:: 213 aacCapabilities); 214 break; 215 case CodecType::APTX: 216 FALLTHROUGH_INTENDED; 217 case CodecType::APTX_HD: 218 ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), 219 CodecCapabilities::Capabilities::hidl_discriminator:: 220 aptxCapabilities); 221 break; 222 case CodecType::LDAC: 223 ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(), 224 CodecCapabilities::Capabilities::hidl_discriminator:: 225 ldacCapabilities); 226 break; 227 case CodecType::UNKNOWN: 228 break; 229 } 230 codec_type_bitmask |= codec_capabilities.codecType; 231 } 232 } 233 } 234 235 // This helps to open the specified provider and check the openProvider() 236 // has corruct return values. BUT, to keep it simple, it does not consider 237 // the capability, and please do so at the SetUp of each session's test. 238 void OpenProviderHelper(const SessionType& session_type) { 239 BluetoothAudioStatus cb_status; 240 auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_]( 241 BluetoothAudioStatus status, 242 const sp<IBluetoothAudioProvider>& provider) { 243 cb_status = status; 244 local_provider = provider; 245 }; 246 auto hidl_retval = providers_factory_->openProvider(session_type, hidl_cb); 247 // HIDL calls should not be failed and callback has to be executed 248 ASSERT_TRUE(hidl_retval.isOk()); 249 if (cb_status == BluetoothAudioStatus::SUCCESS) { 250 ASSERT_NE(session_type, SessionType::UNKNOWN); 251 ASSERT_NE(audio_provider_, nullptr); 252 audio_port_ = new BluetoothAudioPort(*this); 253 } else { 254 // A2DP_HARDWARE_OFFLOAD_DATAPATH is optional 255 ASSERT_TRUE(session_type == SessionType::UNKNOWN || 256 session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); 257 ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE); 258 ASSERT_EQ(audio_provider_, nullptr); 259 } 260 } 261 262 bool IsPcmParametersSupported(const PcmParameters& pcm_parameters) { 263 if (temp_provider_capabilities_.size() != 1 || 264 temp_provider_capabilities_[0].getDiscriminator() != 265 AudioCapabilities::hidl_discriminator::pcmCapabilities) { 266 return false; 267 } 268 auto pcm_capability = temp_provider_capabilities_[0].pcmCapabilities(); 269 bool is_parameter_valid = 270 (pcm_parameters.sampleRate != SampleRate::RATE_UNKNOWN && 271 pcm_parameters.channelMode != ChannelMode::UNKNOWN && 272 pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN); 273 bool is_parameter_in_capability = 274 (pcm_capability.sampleRate & pcm_parameters.sampleRate && 275 pcm_capability.channelMode & pcm_parameters.channelMode && 276 pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample); 277 return is_parameter_valid && is_parameter_in_capability; 278 } 279 280 sp<IBluetoothAudioProvidersFactory> providers_factory_; 281 282 // temp storage saves the specified provider capability by 283 // GetProviderCapabilitiesHelper() 284 std::vector<AudioCapabilities> temp_provider_capabilities_; 285 286 // audio_provider_ is for the Bluetooth stack to report session started/ended 287 // and handled audio stream started / suspended 288 sp<IBluetoothAudioProvider> audio_provider_; 289 290 // audio_port_ is for the Audio HAL to send stream start/suspend/stop commands 291 // to Bluetooth stack 292 sp<IBluetoothAudioPort> audio_port_; 293 294 static constexpr SessionType session_types_[4] = { 295 SessionType::UNKNOWN, SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH, 296 SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH, 297 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH}; 298 }; 299 300 /** 301 * Test whether we can get the FactoryService from HIDL 302 */ 303 TEST_F(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {} 304 305 /** 306 * Test whether we can open a provider for each provider returned by 307 * getProviderCapabilities() with non-empty capabalities 308 */ 309 TEST_F(BluetoothAudioProvidersFactoryHidlTest, 310 OpenProviderAndCheckCapabilitiesBySession) { 311 for (auto session_type : session_types_) { 312 GetProviderCapabilitiesHelper(session_type); 313 OpenProviderHelper(session_type); 314 // We must be able to open a provider if its getProviderCapabilities() 315 // returns non-empty list. 316 EXPECT_TRUE(temp_provider_capabilities_.empty() || 317 audio_provider_ != nullptr); 318 } 319 } 320 321 /** 322 * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH 323 */ 324 class BluetoothAudioProviderA2dpSoftwareHidlTest 325 : public BluetoothAudioProvidersFactoryHidlTest { 326 public: 327 virtual void SetUp() override { 328 BluetoothAudioProvidersFactoryHidlTest::SetUp(); 329 GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); 330 OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH); 331 ASSERT_NE(audio_provider_, nullptr); 332 } 333 334 virtual void TearDown() override { 335 audio_port_ = nullptr; 336 audio_provider_ = nullptr; 337 BluetoothAudioProvidersFactoryHidlTest::TearDown(); 338 } 339 }; 340 341 /** 342 * Test whether we can open a provider of type 343 */ 344 TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {} 345 346 /** 347 * Test whether each provider of type 348 * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with 349 * different PCM config 350 */ 351 TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest, 352 StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) { 353 bool is_codec_config_valid; 354 std::unique_ptr<DataMQ> tempDataMQ; 355 auto hidl_cb = [&is_codec_config_valid, &tempDataMQ]( 356 BluetoothAudioStatus status, 357 const DataMQ::Descriptor& dataMQ) { 358 if (is_codec_config_valid) { 359 ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS); 360 ASSERT_TRUE(dataMQ.isHandleValid()); 361 tempDataMQ.reset(new DataMQ(dataMQ)); 362 } else { 363 EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); 364 EXPECT_FALSE(dataMQ.isHandleValid()); 365 } 366 }; 367 AudioConfiguration audio_config = {}; 368 PcmParameters pcm_parameters = {}; 369 for (auto sample_rate : a2dp_sample_rates) { 370 pcm_parameters.sampleRate = sample_rate; 371 for (auto bits_per_sample : a2dp_bits_per_samples) { 372 pcm_parameters.bitsPerSample = bits_per_sample; 373 for (auto channel_mode : a2dp_channel_modes) { 374 pcm_parameters.channelMode = channel_mode; 375 is_codec_config_valid = IsPcmParametersSupported(pcm_parameters); 376 audio_config.pcmConfig(pcm_parameters); 377 auto hidl_retval = 378 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 379 // HIDL calls should not be failed and callback has to be executed 380 ASSERT_TRUE(hidl_retval.isOk()); 381 if (is_codec_config_valid) { 382 EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid()); 383 } 384 EXPECT_TRUE(audio_provider_->endSession().isOk()); 385 } // ChannelMode 386 } // BitsPerSampple 387 } // SampleRate 388 } 389 390 /** 391 * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH 392 */ 393 class BluetoothAudioProviderA2dpHardwareHidlTest 394 : public BluetoothAudioProvidersFactoryHidlTest { 395 public: 396 virtual void SetUp() override { 397 BluetoothAudioProvidersFactoryHidlTest::SetUp(); 398 GetProviderCapabilitiesHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); 399 OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH); 400 ASSERT_TRUE(temp_provider_capabilities_.empty() || 401 audio_provider_ != nullptr); 402 } 403 404 virtual void TearDown() override { 405 audio_port_ = nullptr; 406 audio_provider_ = nullptr; 407 BluetoothAudioProvidersFactoryHidlTest::TearDown(); 408 } 409 410 bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); } 411 412 void GetOffloadCodecCapabilityHelper(const CodecType& codec_type) { 413 temp_codec_capabilities_ = {}; 414 for (auto codec_capability : temp_provider_capabilities_) { 415 if (codec_capability.codecCapabilities().codecType != codec_type) { 416 continue; 417 } 418 temp_codec_capabilities_ = codec_capability.codecCapabilities(); 419 } 420 } 421 422 std::vector<CodecSpecificConfig> GetSbcCodecSpecificSupportedList( 423 bool supported) { 424 std::vector<CodecSpecificConfig> sbc_codec_specifics; 425 GetOffloadCodecCapabilityHelper(CodecType::SBC); 426 if (temp_codec_capabilities_.codecType != CodecType::SBC) { 427 return sbc_codec_specifics; 428 } 429 // parse the capability 430 SbcParameters sbc_capability = 431 temp_codec_capabilities_.capabilities.sbcCapabilities(); 432 if (sbc_capability.minBitpool > sbc_capability.maxBitpool) { 433 return sbc_codec_specifics; 434 } 435 std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>( 436 sbc_capability.sampleRate, 0xff, supported); 437 std::vector<SbcChannelMode> channel_modes = 438 ExtractValuesFromBitmask<SbcChannelMode>(sbc_capability.channelMode, 439 0x0f, supported); 440 std::vector<SbcBlockLength> block_lengths = 441 ExtractValuesFromBitmask<SbcBlockLength>(sbc_capability.blockLength, 442 0xf0, supported); 443 std::vector<SbcNumSubbands> num_subbandss = 444 ExtractValuesFromBitmask<SbcNumSubbands>(sbc_capability.numSubbands, 445 0x0c, supported); 446 std::vector<SbcAllocMethod> alloc_methods = 447 ExtractValuesFromBitmask<SbcAllocMethod>(sbc_capability.allocMethod, 448 0x03, supported); 449 std::vector<BitsPerSample> bits_per_samples = 450 ExtractValuesFromBitmask<BitsPerSample>(sbc_capability.bitsPerSample, 451 0x07, supported); 452 // combine those parameters into one list of 453 // CodecConfiguration::CodecSpecific 454 CodecSpecificConfig codec_specific = {}; 455 SbcParameters sbc_data; 456 for (auto sample_rate : sample_rates) { 457 for (auto channel_mode : channel_modes) { 458 for (auto block_length : block_lengths) { 459 for (auto num_subbands : num_subbandss) { 460 for (auto alloc_method : alloc_methods) { 461 for (auto bits_per_sample : bits_per_samples) { 462 sbc_data = {.sampleRate = sample_rate, 463 .channelMode = channel_mode, 464 .blockLength = block_length, 465 .numSubbands = num_subbands, 466 .allocMethod = alloc_method, 467 .bitsPerSample = bits_per_sample, 468 .minBitpool = sbc_capability.minBitpool, 469 .maxBitpool = sbc_capability.maxBitpool}; 470 codec_specific.sbcConfig(sbc_data); 471 sbc_codec_specifics.push_back(codec_specific); 472 } 473 } 474 } 475 } 476 } 477 } 478 return sbc_codec_specifics; 479 } 480 481 std::vector<CodecSpecificConfig> GetAacCodecSpecificSupportedList( 482 bool supported) { 483 std::vector<CodecSpecificConfig> aac_codec_specifics; 484 GetOffloadCodecCapabilityHelper(CodecType::AAC); 485 if (temp_codec_capabilities_.codecType != CodecType::AAC) { 486 return aac_codec_specifics; 487 } 488 // parse the capability 489 AacParameters aac_capability = 490 temp_codec_capabilities_.capabilities.aacCapabilities(); 491 std::vector<AacObjectType> object_types = 492 ExtractValuesFromBitmask<AacObjectType>(aac_capability.objectType, 0xf0, 493 supported); 494 std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>( 495 aac_capability.sampleRate, 0xff, supported); 496 std::vector<ChannelMode> channel_modes = 497 ExtractValuesFromBitmask<ChannelMode>(aac_capability.channelMode, 0x03, 498 supported); 499 std::vector<AacVariableBitRate> variable_bit_rate_enableds = { 500 AacVariableBitRate::DISABLED}; 501 if (aac_capability.variableBitRateEnabled == AacVariableBitRate::ENABLED) { 502 variable_bit_rate_enableds.push_back(AacVariableBitRate::ENABLED); 503 } 504 std::vector<BitsPerSample> bits_per_samples = 505 ExtractValuesFromBitmask<BitsPerSample>(aac_capability.bitsPerSample, 506 0x07, supported); 507 // combine those parameters into one list of 508 // CodecConfiguration::CodecSpecific 509 CodecSpecificConfig codec_specific = {}; 510 AacParameters aac_data; 511 for (auto object_type : object_types) { 512 for (auto sample_rate : sample_rates) { 513 for (auto channel_mode : channel_modes) { 514 for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) { 515 for (auto bits_per_sample : bits_per_samples) { 516 aac_data = {.objectType = object_type, 517 .sampleRate = sample_rate, 518 .channelMode = channel_mode, 519 .variableBitRateEnabled = variable_bit_rate_enabled, 520 .bitsPerSample = bits_per_sample}; 521 codec_specific.aacConfig(aac_data); 522 aac_codec_specifics.push_back(codec_specific); 523 } 524 } 525 } 526 } 527 } 528 return aac_codec_specifics; 529 } 530 531 std::vector<CodecSpecificConfig> GetLdacCodecSpecificSupportedList( 532 bool supported) { 533 std::vector<CodecSpecificConfig> ldac_codec_specifics; 534 GetOffloadCodecCapabilityHelper(CodecType::LDAC); 535 if (temp_codec_capabilities_.codecType != CodecType::LDAC) { 536 return ldac_codec_specifics; 537 } 538 // parse the capability 539 LdacParameters ldac_capability = 540 temp_codec_capabilities_.capabilities.ldacCapabilities(); 541 std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>( 542 ldac_capability.sampleRate, 0xff, supported); 543 std::vector<LdacChannelMode> channel_modes = 544 ExtractValuesFromBitmask<LdacChannelMode>(ldac_capability.channelMode, 545 0x07, supported); 546 std::vector<LdacQualityIndex> quality_indexes = { 547 LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID, 548 LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR}; 549 std::vector<BitsPerSample> bits_per_samples = 550 ExtractValuesFromBitmask<BitsPerSample>(ldac_capability.bitsPerSample, 551 0x07, supported); 552 // combine those parameters into one list of 553 // CodecConfiguration::CodecSpecific 554 CodecSpecificConfig codec_specific = {}; 555 LdacParameters ldac_data; 556 for (auto sample_rate : sample_rates) { 557 for (auto channel_mode : channel_modes) { 558 for (auto quality_index : quality_indexes) { 559 for (auto bits_per_sample : bits_per_samples) { 560 ldac_data = {.sampleRate = sample_rate, 561 .channelMode = channel_mode, 562 .qualityIndex = quality_index, 563 .bitsPerSample = bits_per_sample}; 564 codec_specific.ldacConfig(ldac_data); 565 ldac_codec_specifics.push_back(codec_specific); 566 } 567 } 568 } 569 } 570 return ldac_codec_specifics; 571 } 572 573 std::vector<CodecSpecificConfig> GetAptxCodecSpecificSupportedList( 574 bool is_hd, bool supported) { 575 std::vector<CodecSpecificConfig> aptx_codec_specifics; 576 GetOffloadCodecCapabilityHelper( 577 (is_hd ? CodecType::APTX_HD : CodecType::APTX)); 578 if ((is_hd && temp_codec_capabilities_.codecType != CodecType::APTX_HD) || 579 (!is_hd && temp_codec_capabilities_.codecType != CodecType::APTX)) { 580 return aptx_codec_specifics; 581 } 582 // parse the capability 583 AptxParameters aptx_capability = 584 temp_codec_capabilities_.capabilities.aptxCapabilities(); 585 std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>( 586 aptx_capability.sampleRate, 0xff, supported); 587 std::vector<ChannelMode> channel_modes = 588 ExtractValuesFromBitmask<ChannelMode>(aptx_capability.channelMode, 0x03, 589 supported); 590 std::vector<BitsPerSample> bits_per_samples = 591 ExtractValuesFromBitmask<BitsPerSample>(aptx_capability.bitsPerSample, 592 0x07, supported); 593 // combine those parameters into one list of 594 // CodecConfiguration::CodecSpecific 595 CodecSpecificConfig codec_specific = {}; 596 AptxParameters aptx_data; 597 for (auto sample_rate : sample_rates) { 598 for (auto channel_mode : channel_modes) { 599 for (auto bits_per_sample : bits_per_samples) { 600 aptx_data = {.sampleRate = sample_rate, 601 .channelMode = channel_mode, 602 .bitsPerSample = bits_per_sample}; 603 codec_specific.aptxConfig(aptx_data); 604 aptx_codec_specifics.push_back(codec_specific); 605 } 606 } 607 } 608 return aptx_codec_specifics; 609 } 610 611 // temp storage saves the specified codec capability by 612 // GetOffloadCodecCapabilityHelper() 613 CodecCapabilities temp_codec_capabilities_; 614 }; 615 616 /** 617 * Test whether we can open a provider of type 618 */ 619 TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {} 620 621 /** 622 * Test whether each provider of type 623 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with 624 * SBC hardware encoding config 625 */ 626 TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, 627 StartAndEndA2dpSbcHardwareSession) { 628 if (!IsOffloadSupported()) { 629 return; 630 } 631 632 CodecConfiguration codec_config = {}; 633 codec_config.codecType = CodecType::SBC; 634 codec_config.encodedAudioBitrate = 328000; 635 codec_config.peerMtu = 1005; 636 codec_config.isScmstEnabled = false; 637 AudioConfiguration audio_config = {}; 638 std::vector<CodecSpecificConfig> sbc_codec_specifics = 639 GetSbcCodecSpecificSupportedList(true); 640 auto hidl_cb = [](BluetoothAudioStatus status, 641 const DataMQ::Descriptor& dataMQ) { 642 EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); 643 EXPECT_FALSE(dataMQ.isHandleValid()); 644 }; 645 for (auto codec_specific : sbc_codec_specifics) { 646 codec_config.config = codec_specific; 647 audio_config.codecConfig(codec_config); 648 auto hidl_retval = 649 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 650 // HIDL calls should not be failed and callback has to be executed 651 ASSERT_TRUE(hidl_retval.isOk()); 652 EXPECT_TRUE(audio_provider_->endSession().isOk()); 653 } 654 } 655 656 /** 657 * Test whether each provider of type 658 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with 659 * AAC hardware encoding config 660 */ 661 TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, 662 StartAndEndA2dpAacHardwareSession) { 663 if (!IsOffloadSupported()) { 664 return; 665 } 666 667 CodecConfiguration codec_config = {}; 668 codec_config.codecType = CodecType::AAC; 669 codec_config.encodedAudioBitrate = 320000; 670 codec_config.peerMtu = 1005; 671 codec_config.isScmstEnabled = false; 672 AudioConfiguration audio_config = {}; 673 std::vector<CodecSpecificConfig> aac_codec_specifics = 674 GetAacCodecSpecificSupportedList(true); 675 auto hidl_cb = [](BluetoothAudioStatus status, 676 const DataMQ::Descriptor& dataMQ) { 677 EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); 678 EXPECT_FALSE(dataMQ.isHandleValid()); 679 }; 680 for (auto codec_specific : aac_codec_specifics) { 681 codec_config.config = codec_specific; 682 audio_config.codecConfig(codec_config); 683 auto hidl_retval = 684 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 685 // HIDL calls should not be failed and callback has to be executed 686 ASSERT_TRUE(hidl_retval.isOk()); 687 EXPECT_TRUE(audio_provider_->endSession().isOk()); 688 } 689 } 690 691 /** 692 * Test whether each provider of type 693 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with 694 * LDAC hardware encoding config 695 */ 696 TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, 697 StartAndEndA2dpLdacHardwareSession) { 698 if (!IsOffloadSupported()) { 699 return; 700 } 701 702 CodecConfiguration codec_config = {}; 703 codec_config.codecType = CodecType::LDAC; 704 codec_config.encodedAudioBitrate = 990000; 705 codec_config.peerMtu = 1005; 706 codec_config.isScmstEnabled = false; 707 AudioConfiguration audio_config = {}; 708 std::vector<CodecSpecificConfig> ldac_codec_specifics = 709 GetLdacCodecSpecificSupportedList(true); 710 auto hidl_cb = [](BluetoothAudioStatus status, 711 const DataMQ::Descriptor& dataMQ) { 712 EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); 713 EXPECT_FALSE(dataMQ.isHandleValid()); 714 }; 715 for (auto codec_specific : ldac_codec_specifics) { 716 codec_config.config = codec_specific; 717 audio_config.codecConfig(codec_config); 718 auto hidl_retval = 719 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 720 // HIDL calls should not be failed and callback has to be executed 721 ASSERT_TRUE(hidl_retval.isOk()); 722 EXPECT_TRUE(audio_provider_->endSession().isOk()); 723 } 724 } 725 726 /** 727 * Test whether each provider of type 728 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with 729 * AptX hardware encoding config 730 */ 731 TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, 732 StartAndEndA2dpAptxHardwareSession) { 733 if (!IsOffloadSupported()) { 734 return; 735 } 736 737 for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) { 738 CodecConfiguration codec_config = {}; 739 codec_config.codecType = codec_type; 740 codec_config.encodedAudioBitrate = 741 (codec_type == CodecType::APTX ? 352000 : 576000); 742 codec_config.peerMtu = 1005; 743 codec_config.isScmstEnabled = false; 744 AudioConfiguration audio_config = {}; 745 std::vector<CodecSpecificConfig> aptx_codec_specifics = 746 GetAptxCodecSpecificSupportedList( 747 (codec_type == CodecType::APTX_HD ? true : false), true); 748 auto hidl_cb = [](BluetoothAudioStatus status, 749 const DataMQ::Descriptor& dataMQ) { 750 EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS); 751 EXPECT_FALSE(dataMQ.isHandleValid()); 752 }; 753 for (auto codec_specific : aptx_codec_specifics) { 754 codec_config.config = codec_specific; 755 audio_config.codecConfig(codec_config); 756 auto hidl_retval = 757 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 758 // HIDL calls should not be failed and callback has to be executed 759 ASSERT_TRUE(hidl_retval.isOk()); 760 EXPECT_TRUE(audio_provider_->endSession().isOk()); 761 } 762 } 763 } 764 765 /** 766 * Test whether each provider of type 767 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with 768 * an invalid codec config 769 */ 770 TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, 771 StartAndEndA2dpHardwareSessionInvalidCodecConfig) { 772 if (!IsOffloadSupported()) { 773 return; 774 } 775 ASSERT_NE(audio_provider_, nullptr); 776 777 std::vector<CodecSpecificConfig> codec_specifics; 778 for (auto codec_type : a2dp_codec_types) { 779 switch (codec_type) { 780 case CodecType::SBC: 781 codec_specifics = GetSbcCodecSpecificSupportedList(false); 782 break; 783 case CodecType::AAC: 784 codec_specifics = GetAacCodecSpecificSupportedList(false); 785 break; 786 case CodecType::LDAC: 787 codec_specifics = GetLdacCodecSpecificSupportedList(false); 788 break; 789 case CodecType::APTX: 790 codec_specifics = GetAptxCodecSpecificSupportedList(false, false); 791 break; 792 case CodecType::APTX_HD: 793 codec_specifics = GetAptxCodecSpecificSupportedList(true, false); 794 break; 795 case CodecType::UNKNOWN: 796 codec_specifics.clear(); 797 break; 798 } 799 if (codec_specifics.empty()) { 800 continue; 801 } 802 803 CodecConfiguration codec_config = {}; 804 codec_config.codecType = codec_type; 805 codec_config.encodedAudioBitrate = 328000; 806 codec_config.peerMtu = 1005; 807 codec_config.isScmstEnabled = false; 808 AudioConfiguration audio_config = {}; 809 auto hidl_cb = [](BluetoothAudioStatus status, 810 const DataMQ::Descriptor& dataMQ) { 811 EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); 812 EXPECT_FALSE(dataMQ.isHandleValid()); 813 }; 814 for (auto codec_specific : codec_specifics) { 815 codec_config.config = codec_specific; 816 audio_config.codecConfig(codec_config); 817 auto hidl_retval = 818 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 819 // HIDL calls should not be failed and callback has to be executed 820 ASSERT_TRUE(hidl_retval.isOk()); 821 EXPECT_TRUE(audio_provider_->endSession().isOk()); 822 } 823 } 824 } 825 826 /** 827 * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH 828 */ 829 class BluetoothAudioProviderHearingAidSoftwareHidlTest 830 : public BluetoothAudioProvidersFactoryHidlTest { 831 public: 832 virtual void SetUp() override { 833 BluetoothAudioProvidersFactoryHidlTest::SetUp(); 834 GetProviderCapabilitiesHelper( 835 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH); 836 OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH); 837 ASSERT_NE(audio_provider_, nullptr); 838 } 839 840 virtual void TearDown() override { 841 audio_port_ = nullptr; 842 audio_provider_ = nullptr; 843 BluetoothAudioProvidersFactoryHidlTest::TearDown(); 844 } 845 846 static constexpr SampleRate hearing_aid_sample_rates_[3] = { 847 SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000}; 848 static constexpr BitsPerSample hearing_aid_bits_per_samples_[3] = { 849 BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, 850 BitsPerSample::BITS_24}; 851 static constexpr ChannelMode hearing_aid_channel_modes_[3] = { 852 ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO}; 853 }; 854 855 /** 856 * Test whether each provider of type 857 * SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and 858 * stopped with SBC hardware encoding config 859 */ 860 TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest, 861 OpenHearingAidSoftwareProvider) {} 862 863 /** 864 * Test whether each provider of type 865 * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and 866 * stopped with different PCM config 867 */ 868 TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest, 869 StartAndEndHearingAidSessionWithPossiblePcmConfig) { 870 bool is_codec_config_valid; 871 std::unique_ptr<DataMQ> tempDataMQ; 872 auto hidl_cb = [&is_codec_config_valid, &tempDataMQ]( 873 BluetoothAudioStatus status, 874 const DataMQ::Descriptor& dataMQ) { 875 if (is_codec_config_valid) { 876 ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS); 877 ASSERT_TRUE(dataMQ.isHandleValid()); 878 tempDataMQ.reset(new DataMQ(dataMQ)); 879 } else { 880 EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION); 881 EXPECT_FALSE(dataMQ.isHandleValid()); 882 } 883 }; 884 AudioConfiguration audio_config = {}; 885 PcmParameters pcm_parameters = {}; 886 for (auto sample_rate : hearing_aid_sample_rates_) { 887 pcm_parameters.sampleRate = sample_rate; 888 for (auto bits_per_sample : hearing_aid_bits_per_samples_) { 889 pcm_parameters.bitsPerSample = bits_per_sample; 890 for (auto channel_mode : hearing_aid_channel_modes_) { 891 pcm_parameters.channelMode = channel_mode; 892 is_codec_config_valid = IsPcmParametersSupported(pcm_parameters); 893 audio_config.pcmConfig(pcm_parameters); 894 auto hidl_retval = 895 audio_provider_->startSession(audio_port_, audio_config, hidl_cb); 896 // HIDL calls should not be failed and callback has to be executed 897 ASSERT_TRUE(hidl_retval.isOk()); 898 if (is_codec_config_valid) { 899 EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid()); 900 } 901 EXPECT_TRUE(audio_provider_->endSession().isOk()); 902 } // ChannelMode 903 } // BitsPerSampple 904 } // SampleRate 905 } 906 907 int main(int argc, char** argv) { 908 ::testing::AddGlobalTestEnvironment( 909 BluetoothAudioHidlEnvironment::Instance()); 910 ::testing::InitGoogleTest(&argc, argv); 911 BluetoothAudioHidlEnvironment::Instance()->init(&argc, argv); 912 int status = RUN_ALL_TESTS(); 913 LOG(INFO) << "Test result = " << status; 914 return status; 915 } 916