1 /* 2 * Copyright (C) 2017 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 "VtsHalAudioV2_0TargetTest" 18 19 #include <algorithm> 20 #include <cmath> 21 #include <cstddef> 22 #include <cstdio> 23 #include <limits> 24 #include <string> 25 #include <vector> 26 27 #include <VtsHalHidlTargetTestBase.h> 28 29 #include <android-base/logging.h> 30 31 #include <android/hardware/audio/2.0/IDevice.h> 32 #include <android/hardware/audio/2.0/IDevicesFactory.h> 33 #include <android/hardware/audio/2.0/IPrimaryDevice.h> 34 #include <android/hardware/audio/2.0/types.h> 35 #include <android/hardware/audio/common/2.0/types.h> 36 37 #include "utility/AssertOk.h" 38 #include "utility/Documentation.h" 39 #include "utility/EnvironmentTearDown.h" 40 #include "utility/PrettyPrintAudioTypes.h" 41 #include "utility/ReturnIn.h" 42 43 using std::string; 44 using std::to_string; 45 using std::vector; 46 47 using ::android::sp; 48 using ::android::hardware::Return; 49 using ::android::hardware::hidl_handle; 50 using ::android::hardware::hidl_string; 51 using ::android::hardware::hidl_vec; 52 using ::android::hardware::MQDescriptorSync; 53 using ::android::hardware::audio::V2_0::AudioDrain; 54 using ::android::hardware::audio::V2_0::DeviceAddress; 55 using ::android::hardware::audio::V2_0::IDevice; 56 using ::android::hardware::audio::V2_0::IPrimaryDevice; 57 using TtyMode = ::android::hardware::audio::V2_0::IPrimaryDevice::TtyMode; 58 using ::android::hardware::audio::V2_0::IDevicesFactory; 59 using ::android::hardware::audio::V2_0::IStream; 60 using ::android::hardware::audio::V2_0::IStreamIn; 61 using ::android::hardware::audio::V2_0::TimeSpec; 62 using ReadParameters = ::android::hardware::audio::V2_0::IStreamIn::ReadParameters; 63 using ReadStatus = ::android::hardware::audio::V2_0::IStreamIn::ReadStatus; 64 using ::android::hardware::audio::V2_0::IStreamOut; 65 using ::android::hardware::audio::V2_0::IStreamOutCallback; 66 using ::android::hardware::audio::V2_0::MmapBufferInfo; 67 using ::android::hardware::audio::V2_0::MmapPosition; 68 using ::android::hardware::audio::V2_0::ParameterValue; 69 using ::android::hardware::audio::V2_0::Result; 70 using ::android::hardware::audio::common::V2_0::AudioChannelMask; 71 using ::android::hardware::audio::common::V2_0::AudioConfig; 72 using ::android::hardware::audio::common::V2_0::AudioDevice; 73 using ::android::hardware::audio::common::V2_0::AudioFormat; 74 using ::android::hardware::audio::common::V2_0::AudioHandleConsts; 75 using ::android::hardware::audio::common::V2_0::AudioInputFlag; 76 using ::android::hardware::audio::common::V2_0::AudioIoHandle; 77 using ::android::hardware::audio::common::V2_0::AudioMode; 78 using ::android::hardware::audio::common::V2_0::AudioOffloadInfo; 79 using ::android::hardware::audio::common::V2_0::AudioOutputFlag; 80 using ::android::hardware::audio::common::V2_0::AudioSource; 81 using ::android::hardware::audio::common::V2_0::ThreadInfo; 82 83 using namespace ::android::hardware::audio::common::test::utility; 84 85 // Instance to register global tearDown 86 static Environment* environment; 87 88 class HidlTest : public ::testing::VtsHalHidlTargetTestBase { 89 protected: 90 // Convenient member to store results 91 Result res; 92 }; 93 94 ////////////////////////////////////////////////////////////////////////////// 95 ////////////////////// getService audio_devices_factory ////////////////////// 96 ////////////////////////////////////////////////////////////////////////////// 97 98 // Test all audio devices 99 class AudioHidlTest : public HidlTest { 100 public: 101 void SetUp() override { 102 ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base 103 104 if (devicesFactory == nullptr) { 105 environment->registerTearDown([] { devicesFactory.clear(); }); 106 devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService< 107 IDevicesFactory>(); 108 } 109 ASSERT_TRUE(devicesFactory != nullptr); 110 } 111 112 protected: 113 // Cache the devicesFactory retrieval to speed up each test by ~0.5s 114 static sp<IDevicesFactory> devicesFactory; 115 }; 116 sp<IDevicesFactory> AudioHidlTest::devicesFactory; 117 118 TEST_F(AudioHidlTest, GetAudioDevicesFactoryService) { 119 doc::test("test the getService (called in SetUp)"); 120 } 121 122 TEST_F(AudioHidlTest, OpenDeviceInvalidParameter) { 123 doc::test("test passing an invalid parameter to openDevice"); 124 IDevicesFactory::Result result; 125 sp<IDevice> device; 126 ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device(-1), 127 returnIn(result, device))); 128 ASSERT_EQ(IDevicesFactory::Result::INVALID_ARGUMENTS, result); 129 ASSERT_TRUE(device == nullptr); 130 } 131 132 ////////////////////////////////////////////////////////////////////////////// 133 /////////////////////////////// openDevice primary /////////////////////////// 134 ////////////////////////////////////////////////////////////////////////////// 135 136 // Test the primary device 137 class AudioPrimaryHidlTest : public AudioHidlTest { 138 public: 139 /** Primary HAL test are NOT thread safe. */ 140 void SetUp() override { 141 ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base 142 143 if (device == nullptr) { 144 IDevicesFactory::Result result; 145 sp<IDevice> baseDevice; 146 ASSERT_OK( 147 devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY, 148 returnIn(result, baseDevice))); 149 ASSERT_OK(result); 150 ASSERT_TRUE(baseDevice != nullptr); 151 152 environment->registerTearDown([] { device.clear(); }); 153 device = IPrimaryDevice::castFrom(baseDevice); 154 ASSERT_TRUE(device != nullptr); 155 } 156 } 157 158 protected: 159 // Cache the device opening to speed up each test by ~0.5s 160 static sp<IPrimaryDevice> device; 161 }; 162 sp<IPrimaryDevice> AudioPrimaryHidlTest::device; 163 164 TEST_F(AudioPrimaryHidlTest, OpenPrimaryDevice) { 165 doc::test("Test the openDevice (called in SetUp)"); 166 } 167 168 TEST_F(AudioPrimaryHidlTest, Init) { 169 doc::test("Test that the audio primary hal initialized correctly"); 170 ASSERT_OK(device->initCheck()); 171 } 172 173 ////////////////////////////////////////////////////////////////////////////// 174 ///////////////////// {set,get}{Master,Mic}{Mute,Volume} ///////////////////// 175 ////////////////////////////////////////////////////////////////////////////// 176 177 template <class Property> 178 class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest { 179 protected: 180 /** Test a property getter and setter. */ 181 template <class Getter, class Setter> 182 void testAccessors(const string& propertyName, 183 const vector<Property>& valuesToTest, Setter setter, 184 Getter getter, 185 const vector<Property>& invalidValues = {}) { 186 Property initialValue; // Save initial value to restore it at the end 187 // of the test 188 ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue))); 189 ASSERT_OK(res); 190 191 for (Property setValue : valuesToTest) { 192 SCOPED_TRACE("Test " + propertyName + " getter and setter for " + 193 testing::PrintToString(setValue)); 194 ASSERT_OK((device.get()->*setter)(setValue)); 195 Property getValue; 196 // Make sure the getter returns the same value just set 197 ASSERT_OK((device.get()->*getter)(returnIn(res, getValue))); 198 ASSERT_OK(res); 199 EXPECT_EQ(setValue, getValue); 200 } 201 202 for (Property invalidValue : invalidValues) { 203 SCOPED_TRACE("Try to set " + propertyName + 204 " with the invalid value " + 205 testing::PrintToString(invalidValue)); 206 EXPECT_RESULT(Result::INVALID_ARGUMENTS, 207 (device.get()->*setter)(invalidValue)); 208 } 209 210 ASSERT_OK( 211 (device.get()->*setter)(initialValue)); // restore initial value 212 } 213 214 /** Test the getter and setter of an optional feature. */ 215 template <class Getter, class Setter> 216 void testOptionalAccessors(const string& propertyName, 217 const vector<Property>& valuesToTest, 218 Setter setter, Getter getter, 219 const vector<Property>& invalidValues = {}) { 220 doc::test("Test the optional " + propertyName + " getters and setter"); 221 { 222 SCOPED_TRACE("Test feature support by calling the getter"); 223 Property initialValue; 224 ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue))); 225 if (res == Result::NOT_SUPPORTED) { 226 doc::partialTest(propertyName + " getter is not supported"); 227 return; 228 } 229 ASSERT_OK(res); // If it is supported it must succeed 230 } 231 // The feature is supported, test it 232 testAccessors(propertyName, valuesToTest, setter, getter, 233 invalidValues); 234 } 235 }; 236 237 using BoolAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<bool>; 238 239 TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) { 240 doc::test("Check that the mic can be muted and unmuted"); 241 testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute, 242 &IDevice::getMicMute); 243 // TODO: check that the mic is really muted (all sample are 0) 244 } 245 246 TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) { 247 doc::test( 248 "If master mute is supported, try to mute and unmute the master " 249 "output"); 250 testOptionalAccessors("master mute", {true, false, true}, 251 &IDevice::setMasterMute, &IDevice::getMasterMute); 252 // TODO: check that the master volume is really muted 253 } 254 255 using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<float>; 256 TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) { 257 doc::test("Test the master volume if supported"); 258 testOptionalAccessors("master volume", {0, 0.5, 1}, 259 &IDevice::setMasterVolume, &IDevice::getMasterVolume, 260 {-0.1, 1.1, NAN, INFINITY, -INFINITY, 261 1 + std::numeric_limits<float>::epsilon()}); 262 // TODO: check that the master volume is really changed 263 } 264 265 ////////////////////////////////////////////////////////////////////////////// 266 //////////////////////////////// AudioPatches //////////////////////////////// 267 ////////////////////////////////////////////////////////////////////////////// 268 269 class AudioPatchPrimaryHidlTest : public AudioPrimaryHidlTest { 270 protected: 271 bool areAudioPatchesSupported() { 272 auto result = device->supportsAudioPatches(); 273 EXPECT_IS_OK(result); 274 return result; 275 } 276 }; 277 278 TEST_F(AudioPatchPrimaryHidlTest, AudioPatches) { 279 doc::test("Test if audio patches are supported"); 280 if (!areAudioPatchesSupported()) { 281 doc::partialTest("Audio patches are not supported"); 282 return; 283 } 284 // TODO: test audio patches 285 } 286 287 ////////////////////////////////////////////////////////////////////////////// 288 //////////////// Required and recommended audio format support /////////////// 289 // From: 290 // https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording 291 // From: 292 // https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback 293 /////////// TODO: move to the beginning of the file for easier update //////// 294 ////////////////////////////////////////////////////////////////////////////// 295 296 class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest { 297 public: 298 // Cache result ? 299 static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() { 300 return combineAudioConfig( 301 {AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, 302 {8000, 11025, 16000, 22050, 32000, 44100}, 303 {AudioFormat::PCM_16_BIT}); 304 } 305 306 static const vector<AudioConfig> 307 getRecommendedSupportPlaybackAudioConfig() { 308 return combineAudioConfig( 309 {AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, 310 {24000, 48000}, {AudioFormat::PCM_16_BIT}); 311 } 312 313 static const vector<AudioConfig> getSupportedPlaybackAudioConfig() { 314 // TODO: retrieve audio config supported by the platform 315 // as declared in the policy configuration 316 return {}; 317 } 318 319 static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() { 320 return combineAudioConfig({AudioChannelMask::IN_MONO}, 321 {8000, 11025, 16000, 44100}, 322 {AudioFormat::PCM_16_BIT}); 323 } 324 static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() { 325 return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, 326 {AudioFormat::PCM_16_BIT}); 327 } 328 static const vector<AudioConfig> getSupportedCaptureAudioConfig() { 329 // TODO: retrieve audio config supported by the platform 330 // as declared in the policy configuration 331 return {}; 332 } 333 334 private: 335 static const vector<AudioConfig> combineAudioConfig( 336 vector<AudioChannelMask> channelMasks, vector<uint32_t> sampleRates, 337 vector<AudioFormat> formats) { 338 vector<AudioConfig> configs; 339 for (auto channelMask : channelMasks) { 340 for (auto sampleRate : sampleRates) { 341 for (auto format : formats) { 342 AudioConfig config{}; 343 // leave offloadInfo to 0 344 config.channelMask = channelMask; 345 config.sampleRateHz = sampleRate; 346 config.format = format; 347 // FIXME: leave frameCount to 0 ? 348 configs.push_back(config); 349 } 350 } 351 } 352 return configs; 353 } 354 }; 355 356 /** Generate a test name based on an audio config. 357 * 358 * As the only parameter changing are channel mask and sample rate, 359 * only print those ones in the test name. 360 */ 361 static string generateTestName( 362 const testing::TestParamInfo<AudioConfig>& info) { 363 const AudioConfig& config = info.param; 364 return to_string(info.index) + "__" + to_string(config.sampleRateHz) + "_" + 365 // "MONO" is more clear than "FRONT_LEFT" 366 ((config.channelMask == AudioChannelMask::OUT_MONO || 367 config.channelMask == AudioChannelMask::IN_MONO) 368 ? "MONO" 369 : toString(config.channelMask)); 370 } 371 372 ////////////////////////////////////////////////////////////////////////////// 373 ///////////////////////////// getInputBufferSize ///////////////////////////// 374 ////////////////////////////////////////////////////////////////////////////// 375 376 // FIXME: execute input test only if platform declares 377 // android.hardware.microphone 378 // how to get this value ? is it a property ??? 379 380 class AudioCaptureConfigPrimaryTest 381 : public AudioConfigPrimaryTest, 382 public ::testing::WithParamInterface<AudioConfig> { 383 protected: 384 void inputBufferSizeTest(const AudioConfig& audioConfig, 385 bool supportRequired) { 386 uint64_t bufferSize; 387 ASSERT_OK( 388 device->getInputBufferSize(audioConfig, returnIn(res, bufferSize))); 389 390 switch (res) { 391 case Result::INVALID_ARGUMENTS: 392 EXPECT_FALSE(supportRequired); 393 break; 394 case Result::OK: 395 // Check that the buffer is of a sane size 396 // For now only that it is > 0 397 EXPECT_GT(bufferSize, uint64_t(0)); 398 break; 399 default: 400 FAIL() << "Invalid return status: " 401 << ::testing::PrintToString(res); 402 } 403 } 404 }; 405 406 // Test that the required capture config and those declared in the policy are 407 // indeed supported 408 class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {}; 409 TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) { 410 doc::test( 411 "Input buffer size must be retrievable for a format with required " 412 "support."); 413 inputBufferSizeTest(GetParam(), true); 414 } 415 INSTANTIATE_TEST_CASE_P( 416 RequiredInputBufferSize, RequiredInputBufferSizeTest, 417 ::testing::ValuesIn( 418 AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()), 419 &generateTestName); 420 INSTANTIATE_TEST_CASE_P( 421 SupportedInputBufferSize, RequiredInputBufferSizeTest, 422 ::testing::ValuesIn( 423 AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()), 424 &generateTestName); 425 426 // Test that the recommended capture config are supported or lead to a 427 // INVALID_ARGUMENTS return 428 class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {}; 429 TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) { 430 doc::test( 431 "Input buffer size should be retrievable for a format with recommended " 432 "support."); 433 inputBufferSizeTest(GetParam(), false); 434 } 435 INSTANTIATE_TEST_CASE_P( 436 RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest, 437 ::testing::ValuesIn( 438 AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()), 439 &generateTestName); 440 441 ////////////////////////////////////////////////////////////////////////////// 442 /////////////////////////////// setScreenState /////////////////////////////// 443 ////////////////////////////////////////////////////////////////////////////// 444 445 TEST_F(AudioPrimaryHidlTest, setScreenState) { 446 doc::test("Check that the hal can receive the screen state"); 447 for (bool turnedOn : {false, true, true, false, false}) { 448 auto ret = device->setScreenState(turnedOn); 449 ASSERT_IS_OK(ret); 450 Result result = ret; 451 auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED}; 452 ASSERT_RESULT(okOrNotSupported, result); 453 } 454 } 455 456 ////////////////////////////////////////////////////////////////////////////// 457 //////////////////////////// {get,set}Parameters ///////////////////////////// 458 ////////////////////////////////////////////////////////////////////////////// 459 460 TEST_F(AudioPrimaryHidlTest, getParameters) { 461 doc::test("Check that the hal can set and get parameters"); 462 hidl_vec<hidl_string> keys; 463 hidl_vec<ParameterValue> values; 464 ASSERT_OK(device->getParameters(keys, returnIn(res, values))); 465 ASSERT_OK(device->setParameters(values)); 466 values.resize(0); 467 ASSERT_OK(device->setParameters(values)); 468 } 469 470 ////////////////////////////////////////////////////////////////////////////// 471 //////////////////////////////// debugDebug ////////////////////////////////// 472 ////////////////////////////////////////////////////////////////////////////// 473 474 template <class DebugDump> 475 static void testDebugDump(DebugDump debugDump) { 476 // Dump in a temporary file 477 // Note that SELinux must be deactivate for this test to work 478 FILE* file = tmpfile(); 479 ASSERT_NE(nullptr, file) << errno; 480 481 // Wrap the temporary file file descriptor in a native handle 482 auto* nativeHandle = native_handle_create(1, 0); 483 ASSERT_NE(nullptr, nativeHandle); 484 nativeHandle->data[0] = fileno(file); 485 486 // Wrap this native handle in a hidl handle 487 hidl_handle handle; 488 handle.setTo(nativeHandle, true /*take ownership*/); 489 490 ASSERT_OK(debugDump(handle)); 491 492 // Check that at least one bit was written by the hal 493 // TODO: debugDump does not return a Result. 494 // This mean that the hal can not report that it not implementing the 495 // function. 496 rewind(file); // can not fail 497 char buff; 498 if (fread(&buff, sizeof(buff), 1, file) != 1) { 499 doc::note("debugDump does not seem implemented"); 500 } 501 EXPECT_EQ(0, fclose(file)) << errno; 502 } 503 504 TEST_F(AudioPrimaryHidlTest, DebugDump) { 505 doc::test("Check that the hal can dump its state without error"); 506 testDebugDump([](const auto& handle) { return device->debugDump(handle); }); 507 } 508 509 TEST_F(AudioPrimaryHidlTest, DebugDumpInvalidArguments) { 510 doc::test("Check that the hal dump doesn't crash on invalid arguments"); 511 ASSERT_OK(device->debugDump(hidl_handle())); 512 } 513 514 ////////////////////////////////////////////////////////////////////////////// 515 ////////////////////////// open{Output,Input}Stream ////////////////////////// 516 ////////////////////////////////////////////////////////////////////////////// 517 518 template <class Stream> 519 class OpenStreamTest : public AudioConfigPrimaryTest, 520 public ::testing::WithParamInterface<AudioConfig> { 521 protected: 522 template <class Open> 523 void testOpen(Open openStream, const AudioConfig& config) { 524 // FIXME: Open a stream without an IOHandle 525 // This is not required to be accepted by hal implementations 526 AudioIoHandle ioHandle = 527 (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE; 528 AudioConfig suggestedConfig{}; 529 ASSERT_OK(openStream(ioHandle, config, 530 returnIn(res, stream, suggestedConfig))); 531 532 // TODO: only allow failure for RecommendedPlaybackAudioConfig 533 switch (res) { 534 case Result::OK: 535 ASSERT_TRUE(stream != nullptr); 536 audioConfig = config; 537 break; 538 case Result::INVALID_ARGUMENTS: 539 ASSERT_TRUE(stream == nullptr); 540 AudioConfig suggestedConfigRetry; 541 // Could not open stream with config, try again with the 542 // suggested one 543 ASSERT_OK( 544 openStream(ioHandle, suggestedConfig, 545 returnIn(res, stream, suggestedConfigRetry))); 546 // This time it must succeed 547 ASSERT_OK(res); 548 ASSERT_TRUE(stream != nullptr); 549 audioConfig = suggestedConfig; 550 break; 551 default: 552 FAIL() << "Invalid return status: " 553 << ::testing::PrintToString(res); 554 } 555 open = true; 556 } 557 558 Return<Result> closeStream() { 559 open = false; 560 return stream->close(); 561 } 562 563 private: 564 void TearDown() override { 565 if (open) { 566 ASSERT_OK(stream->close()); 567 } 568 } 569 570 protected: 571 AudioConfig audioConfig; 572 DeviceAddress address = {}; 573 sp<Stream> stream; 574 bool open = false; 575 }; 576 577 ////////////////////////////// openOutputStream ////////////////////////////// 578 579 class OutputStreamTest : public OpenStreamTest<IStreamOut> { 580 virtual void SetUp() override { 581 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base 582 address.device = AudioDevice::OUT_DEFAULT; 583 const AudioConfig& config = GetParam(); 584 AudioOutputFlag flags = 585 AudioOutputFlag::NONE; // TODO: test all flag combination 586 testOpen( 587 [&](AudioIoHandle handle, AudioConfig config, auto cb) { 588 return device->openOutputStream(handle, address, config, flags, 589 cb); 590 }, 591 config); 592 } 593 }; 594 TEST_P(OutputStreamTest, OpenOutputStreamTest) { 595 doc::test( 596 "Check that output streams can be open with the required and " 597 "recommended config"); 598 // Open done in SetUp 599 } 600 INSTANTIATE_TEST_CASE_P( 601 RequiredOutputStreamConfigSupport, OutputStreamTest, 602 ::testing::ValuesIn( 603 AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()), 604 &generateTestName); 605 INSTANTIATE_TEST_CASE_P( 606 SupportedOutputStreamConfig, OutputStreamTest, 607 ::testing::ValuesIn( 608 AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()), 609 &generateTestName); 610 611 INSTANTIATE_TEST_CASE_P( 612 RecommendedOutputStreamConfigSupport, OutputStreamTest, 613 ::testing::ValuesIn( 614 AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()), 615 &generateTestName); 616 617 ////////////////////////////// openInputStream ////////////////////////////// 618 619 class InputStreamTest : public OpenStreamTest<IStreamIn> { 620 virtual void SetUp() override { 621 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base 622 address.device = AudioDevice::IN_DEFAULT; 623 const AudioConfig& config = GetParam(); 624 AudioInputFlag flags = 625 AudioInputFlag::NONE; // TODO: test all flag combination 626 AudioSource source = 627 AudioSource::DEFAULT; // TODO: test all flag combination 628 testOpen( 629 [&](AudioIoHandle handle, AudioConfig config, auto cb) { 630 return device->openInputStream(handle, address, config, flags, 631 source, cb); 632 }, 633 config); 634 } 635 }; 636 637 TEST_P(InputStreamTest, OpenInputStreamTest) { 638 doc::test( 639 "Check that input streams can be open with the required and " 640 "recommended config"); 641 // Open done in setup 642 } 643 INSTANTIATE_TEST_CASE_P( 644 RequiredInputStreamConfigSupport, InputStreamTest, 645 ::testing::ValuesIn( 646 AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()), 647 &generateTestName); 648 INSTANTIATE_TEST_CASE_P( 649 SupportedInputStreamConfig, InputStreamTest, 650 ::testing::ValuesIn( 651 AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()), 652 &generateTestName); 653 654 INSTANTIATE_TEST_CASE_P( 655 RecommendedInputStreamConfigSupport, InputStreamTest, 656 ::testing::ValuesIn( 657 AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()), 658 &generateTestName); 659 660 ////////////////////////////////////////////////////////////////////////////// 661 ////////////////////////////// IStream getters /////////////////////////////// 662 ////////////////////////////////////////////////////////////////////////////// 663 664 /** Unpack the provided result. 665 * If the result is not OK, register a failure and return an undefined value. */ 666 template <class R> 667 static R extract(Return<R> ret) { 668 if (!ret.isOk()) { 669 EXPECT_IS_OK(ret); 670 return R{}; 671 } 672 return ret; 673 } 674 675 /* Could not find a way to write a test for two parametrized class fixure 676 * thus use this macro do duplicate tests for Input and Output stream */ 677 #define TEST_IO_STREAM(test_name, documentation, code) \ 678 TEST_P(InputStreamTest, test_name) { \ 679 doc::test(documentation); \ 680 code; \ 681 } \ 682 TEST_P(OutputStreamTest, test_name) { \ 683 doc::test(documentation); \ 684 code; \ 685 } 686 687 TEST_IO_STREAM( 688 GetFrameCount, 689 "Check that the stream frame count == the one it was opened with", 690 ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount()))) 691 692 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with", 693 ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate()))) 694 695 TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it was opened with", 696 ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask()))) 697 698 TEST_IO_STREAM(GetFormat, 699 "Check that the stream format == the one it was opened with", 700 ASSERT_EQ(audioConfig.format, extract(stream->getFormat()))) 701 702 // TODO: for now only check that the framesize is not incoherent 703 TEST_IO_STREAM(GetFrameSize, 704 "Check that the stream frame size == the one it was opened with", 705 ASSERT_GT(extract(stream->getFrameSize()), 0U)) 706 707 TEST_IO_STREAM(GetBufferSize, 708 "Check that the stream buffer size== the one it was opened with", 709 ASSERT_GE(extract(stream->getBufferSize()), 710 extract(stream->getFrameSize()))); 711 712 template <class Property, class CapabilityGetter, class Getter, class Setter> 713 static void testCapabilityGetter(const string& name, IStream* stream, 714 Property currentValue, 715 CapabilityGetter capablityGetter, 716 Getter getter, Setter setter) { 717 hidl_vec<Property> capabilities; 718 ASSERT_OK((stream->*capablityGetter)(returnIn(capabilities))); 719 if (capabilities.size() == 0) { 720 // The default hal should probably return a NOT_SUPPORTED if the hal 721 // does not expose 722 // capability retrieval. For now it returns an empty list if not 723 // implemented 724 doc::partialTest(name + " is not supported"); 725 return; 726 }; 727 // TODO: This code has never been tested on a hal that supports 728 // getSupportedSampleRates 729 EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue), 730 capabilities.end()) 731 << "current " << name << " is not in the list of the supported ones " 732 << toString(capabilities); 733 734 // Check that all declared supported values are indeed supported 735 for (auto capability : capabilities) { 736 ASSERT_OK((stream->*setter)(capability)); 737 ASSERT_EQ(capability, extract((stream->*getter)())); 738 } 739 } 740 741 TEST_IO_STREAM(SupportedSampleRate, 742 "Check that the stream sample rate is declared as supported", 743 testCapabilityGetter("getSupportedSampleRate", stream.get(), 744 extract(stream->getSampleRate()), 745 &IStream::getSupportedSampleRates, 746 &IStream::getSampleRate, 747 &IStream::setSampleRate)) 748 749 TEST_IO_STREAM(SupportedChannelMask, 750 "Check that the stream channel mask is declared as supported", 751 testCapabilityGetter("getSupportedChannelMask", stream.get(), 752 extract(stream->getChannelMask()), 753 &IStream::getSupportedChannelMasks, 754 &IStream::getChannelMask, 755 &IStream::setChannelMask)) 756 757 TEST_IO_STREAM(SupportedFormat, 758 "Check that the stream format is declared as supported", 759 testCapabilityGetter("getSupportedFormat", stream.get(), 760 extract(stream->getFormat()), 761 &IStream::getSupportedFormats, 762 &IStream::getFormat, &IStream::setFormat)) 763 764 static void testGetDevice(IStream* stream, AudioDevice expectedDevice) { 765 // Unfortunately the interface does not allow the implementation to return 766 // NOT_SUPPORTED 767 // Thus allow NONE as signaling that the call is not supported. 768 auto ret = stream->getDevice(); 769 ASSERT_IS_OK(ret); 770 AudioDevice device = ret; 771 ASSERT_TRUE(device == expectedDevice || device == AudioDevice::NONE) 772 << "Expected: " << ::testing::PrintToString(expectedDevice) 773 << "\n Actual: " << ::testing::PrintToString(device); 774 } 775 776 TEST_IO_STREAM(GetDevice, 777 "Check that the stream device == the one it was opened with", 778 areAudioPatchesSupported() 779 ? doc::partialTest("Audio patches are supported") 780 : testGetDevice(stream.get(), address.device)) 781 782 static void testSetDevice(IStream* stream, const DeviceAddress& address) { 783 DeviceAddress otherAddress = address; 784 otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 785 ? AudioDevice::OUT_SPEAKER 786 : AudioDevice::IN_BUILTIN_MIC; 787 EXPECT_OK(stream->setDevice(otherAddress)); 788 789 ASSERT_OK(stream->setDevice(address)); // Go back to the original value 790 } 791 792 TEST_IO_STREAM( 793 SetDevice, 794 "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC", 795 areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported") 796 : testSetDevice(stream.get(), address)) 797 798 static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) { 799 uint32_t sampleRateHz; 800 AudioChannelMask mask; 801 AudioFormat format; 802 803 stream->getAudioProperties(returnIn(sampleRateHz, mask, format)); 804 805 // FIXME: the qcom hal it does not currently negotiate the sampleRate & 806 // channel mask 807 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz); 808 EXPECT_EQ(expectedConfig.channelMask, mask); 809 EXPECT_EQ(expectedConfig.format, format); 810 } 811 812 TEST_IO_STREAM(GetAudioProperties, 813 "Check that the stream audio properties == the ones it was opened with", 814 testGetAudioProperties(stream.get(), audioConfig)) 815 816 static void testConnectedState(IStream* stream) { 817 DeviceAddress address = {}; 818 using AD = AudioDevice; 819 for (auto device : 820 {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) { 821 address.device = device; 822 823 ASSERT_OK(stream->setConnectedState(address, true)); 824 ASSERT_OK(stream->setConnectedState(address, false)); 825 } 826 } 827 TEST_IO_STREAM(SetConnectedState, 828 "Check that the stream can be notified of device connection and " 829 "deconnection", 830 testConnectedState(stream.get())) 831 832 static auto invalidArgsOrNotSupportedOrOK = {Result::INVALID_ARGUMENTS, 833 Result::NOT_SUPPORTED, Result::OK}; 834 TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value", 835 ASSERT_RESULT(invalidArgsOrNotSupportedOrOK, 836 stream->setHwAvSync(666))) 837 838 TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", 839 ASSERT_IS_OK(device->getHwAvSync())); 840 841 static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys, 842 vector<Result> expectedResults) { 843 hidl_vec<ParameterValue> parameters; 844 Result res; 845 ASSERT_OK(stream->getParameters(keys, returnIn(res, parameters))); 846 ASSERT_RESULT(expectedResults, res); 847 if (res == Result::OK) { 848 for (auto& parameter : parameters) { 849 ASSERT_EQ(0U, parameter.value.size()) << toString(parameter); 850 } 851 } 852 } 853 854 /* Get/Set parameter is intended to be an opaque channel between vendors app and 855 * their HALs. 856 * Thus can not be meaningfully tested. 857 */ 858 TEST_IO_STREAM(getEmptySetParameter, "Retrieve the values of an empty set", 859 checkGetNoParameter(stream.get(), {} /* keys */, {Result::OK})) 860 861 TEST_IO_STREAM(getNonExistingParameter, 862 "Retrieve the values of an non existing parameter", 863 checkGetNoParameter(stream.get(), 864 {"Non existing key"} /* keys */, 865 {Result::NOT_SUPPORTED})) 866 867 TEST_IO_STREAM(setEmptySetParameter, 868 "Set the values of an empty set of parameters", 869 ASSERT_RESULT(Result::OK, stream->setParameters({}))) 870 871 TEST_IO_STREAM( 872 setNonExistingParameter, "Set the values of an non existing parameter", 873 // Unfortunately, the set_parameter legacy interface did not return any 874 // error code when a key is not supported. 875 // To allow implementation to just wrapped the legacy one, consider OK as a 876 // valid result for setting a non existing parameter. 877 ASSERT_RESULT(invalidArgsOrNotSupportedOrOK, 878 stream->setParameters({{"non existing key", "0"}}))) 879 880 TEST_IO_STREAM(DebugDump, 881 "Check that a stream can dump its state without error", 882 testDebugDump([this](const auto& handle) { 883 return stream->debugDump(handle); 884 })) 885 886 TEST_IO_STREAM(DebugDumpInvalidArguments, 887 "Check that the stream dump doesn't crash on invalid arguments", 888 ASSERT_OK(stream->debugDump(hidl_handle()))) 889 890 ////////////////////////////////////////////////////////////////////////////// 891 ////////////////////////////// addRemoveEffect /////////////////////////////// 892 ////////////////////////////////////////////////////////////////////////////// 893 894 TEST_IO_STREAM(AddNonExistingEffect, "Adding a non existing effect should fail", 895 ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->addEffect(666))) 896 TEST_IO_STREAM(RemoveNonExistingEffect, 897 "Removing a non existing effect should fail", 898 ASSERT_RESULT(Result::INVALID_ARGUMENTS, 899 stream->removeEffect(666))) 900 901 // TODO: positive tests 902 903 ////////////////////////////////////////////////////////////////////////////// 904 /////////////////////////////// Control //////////////////////////////// 905 ////////////////////////////////////////////////////////////////////////////// 906 907 TEST_IO_STREAM(standby, "Make sure the stream can be put in stanby", 908 ASSERT_OK(stream->standby())) // can not fail 909 910 static vector<Result> invalidStateOrNotSupported = {Result::INVALID_STATE, 911 Result::NOT_SUPPORTED}; 912 913 TEST_IO_STREAM(startNoMmap, 914 "Starting a mmaped stream before mapping it should fail", 915 ASSERT_RESULT(invalidStateOrNotSupported, stream->start())) 916 917 TEST_IO_STREAM(stopNoMmap, 918 "Stopping a mmaped stream before mapping it should fail", 919 ASSERT_RESULT(invalidStateOrNotSupported, stream->stop())) 920 921 TEST_IO_STREAM(getMmapPositionNoMmap, 922 "Get a stream Mmap position before mapping it should fail", 923 ASSERT_RESULT(invalidStateOrNotSupported, stream->stop())) 924 925 TEST_IO_STREAM(close, "Make sure a stream can be closed", 926 ASSERT_OK(closeStream())) 927 TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice", 928 ASSERT_OK(closeStream()); 929 ASSERT_RESULT(Result::INVALID_STATE, closeStream())) 930 931 static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, 932 Result::NOT_SUPPORTED}; 933 static void testCreateTooBigMmapBuffer(IStream* stream) { 934 MmapBufferInfo info; 935 Result res; 936 // Assume that int max is a value too big to be allocated 937 // This is true currently with a 32bit media server, but might not when it 938 // will run in 64 bit 939 auto minSizeFrames = std::numeric_limits<int32_t>::max(); 940 ASSERT_OK(stream->createMmapBuffer(minSizeFrames, returnIn(res, info))); 941 ASSERT_RESULT(invalidArgsOrNotSupported, res); 942 } 943 944 TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer too big should fail", 945 testCreateTooBigMmapBuffer(stream.get())) 946 947 static void testGetMmapPositionOfNonMmapedStream(IStream* stream) { 948 Result res; 949 MmapPosition position; 950 ASSERT_OK(stream->getMmapPosition(returnIn(res, position))); 951 ASSERT_RESULT(invalidArgsOrNotSupported, res); 952 } 953 954 TEST_IO_STREAM( 955 GetMmapPositionOfNonMmapedStream, 956 "Retrieving the mmap position of a non mmaped stream should fail", 957 testGetMmapPositionOfNonMmapedStream(stream.get())) 958 959 ////////////////////////////////////////////////////////////////////////////// 960 ///////////////////////////////// StreamIn /////////////////////////////////// 961 ////////////////////////////////////////////////////////////////////////////// 962 963 TEST_P(InputStreamTest, GetAudioSource) { 964 doc::test( 965 "Retrieving the audio source of an input stream should always succeed"); 966 AudioSource source; 967 ASSERT_OK(stream->getAudioSource(returnIn(res, source))); 968 if (res == Result::NOT_SUPPORTED) { 969 doc::partialTest("getAudioSource is not supported"); 970 return; 971 } 972 ASSERT_OK(res); 973 ASSERT_EQ(AudioSource::DEFAULT, source); 974 } 975 976 static void testUnitaryGain(std::function<Return<Result>(float)> setGain) { 977 for (float value : 978 (float[]){-INFINITY, -1.0, 1.0 + std::numeric_limits<float>::epsilon(), 979 2.0, INFINITY, NAN}) { 980 EXPECT_RESULT(Result::INVALID_ARGUMENTS, setGain(value)) << "value=" 981 << value; 982 } 983 // Do not consider -0.0 as an invalid value as it is == with 0.0 984 for (float value : {-0.0, 0.0, 0.01, 0.5, 0.09, 1.0 /* Restore volume*/}) { 985 EXPECT_OK(setGain(value)) << "value=" << value; 986 } 987 } 988 989 static void testOptionalUnitaryGain( 990 std::function<Return<Result>(float)> setGain, string debugName) { 991 auto result = setGain(1); 992 ASSERT_IS_OK(result); 993 if (result == Result::NOT_SUPPORTED) { 994 doc::partialTest(debugName + " is not supported"); 995 return; 996 } 997 testUnitaryGain(setGain); 998 } 999 1000 TEST_P(InputStreamTest, SetGain) { 1001 doc::test("The gain of an input stream should only be set between [0,1]"); 1002 testOptionalUnitaryGain( 1003 [this](float volume) { return stream->setGain(volume); }, 1004 "InputStream::setGain"); 1005 } 1006 1007 static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, 1008 uint32_t framesCount) { 1009 Result res; 1010 // Ignore output parameters as the call should fail 1011 ASSERT_OK(stream->prepareForReading( 1012 frameSize, framesCount, 1013 [&res](auto r, auto&, auto&, auto&, auto&) { res = r; })); 1014 EXPECT_RESULT(Result::INVALID_ARGUMENTS, res); 1015 } 1016 1017 TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) { 1018 doc::test( 1019 "Preparing a stream for reading with a 0 sized buffer should fail"); 1020 testPrepareForReading(stream.get(), 0, 0); 1021 } 1022 1023 TEST_P(InputStreamTest, PrepareForReadingWithHugeBuffer) { 1024 doc::test( 1025 "Preparing a stream for reading with a 2^32 sized buffer should fail"); 1026 testPrepareForReading(stream.get(), 1, 1027 std::numeric_limits<uint32_t>::max()); 1028 } 1029 1030 TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) { 1031 doc::test( 1032 "Preparing a stream for reading with a overflowing sized buffer should " 1033 "fail"); 1034 auto uintMax = std::numeric_limits<uint32_t>::max(); 1035 testPrepareForReading(stream.get(), uintMax, uintMax); 1036 } 1037 1038 TEST_P(InputStreamTest, GetInputFramesLost) { 1039 doc::test( 1040 "The number of frames lost on a never started stream should be 0"); 1041 auto ret = stream->getInputFramesLost(); 1042 ASSERT_IS_OK(ret); 1043 uint32_t framesLost{ret}; 1044 ASSERT_EQ(0U, framesLost); 1045 } 1046 1047 TEST_P(InputStreamTest, getCapturePosition) { 1048 doc::test( 1049 "The capture position of a non prepared stream should not be " 1050 "retrievable"); 1051 uint64_t frames; 1052 uint64_t time; 1053 ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time))); 1054 ASSERT_RESULT(invalidStateOrNotSupported, res); 1055 } 1056 1057 ////////////////////////////////////////////////////////////////////////////// 1058 ///////////////////////////////// StreamIn /////////////////////////////////// 1059 ////////////////////////////////////////////////////////////////////////////// 1060 1061 TEST_P(OutputStreamTest, getLatency) { 1062 doc::test("Make sure latency is over 0"); 1063 auto result = stream->getLatency(); 1064 ASSERT_IS_OK(result); 1065 ASSERT_GT(result, 0U); 1066 } 1067 1068 TEST_P(OutputStreamTest, setVolume) { 1069 doc::test("Try to set the output volume"); 1070 testOptionalUnitaryGain( 1071 [this](float volume) { return stream->setVolume(volume, volume); }, 1072 "setVolume"); 1073 } 1074 1075 static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, 1076 uint32_t framesCount) { 1077 Result res; 1078 // Ignore output parameters as the call should fail 1079 ASSERT_OK(stream->prepareForWriting( 1080 frameSize, framesCount, 1081 [&res](auto r, auto&, auto&, auto&, auto&) { res = r; })); 1082 EXPECT_RESULT(Result::INVALID_ARGUMENTS, res); 1083 } 1084 1085 TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) { 1086 doc::test( 1087 "Preparing a stream for writing with a 0 sized buffer should fail"); 1088 testPrepareForWriting(stream.get(), 0, 0); 1089 } 1090 1091 TEST_P(OutputStreamTest, PrepareForWriteWithHugeBuffer) { 1092 doc::test( 1093 "Preparing a stream for writing with a 2^32 sized buffer should fail"); 1094 testPrepareForWriting(stream.get(), 1, 1095 std::numeric_limits<uint32_t>::max()); 1096 } 1097 1098 TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) { 1099 doc::test( 1100 "Preparing a stream for writing with a overflowing sized buffer should " 1101 "fail"); 1102 auto uintMax = std::numeric_limits<uint32_t>::max(); 1103 testPrepareForWriting(stream.get(), uintMax, uintMax); 1104 } 1105 1106 struct Capability { 1107 Capability(IStreamOut* stream) { 1108 EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume))); 1109 auto ret = stream->supportsDrain(); 1110 EXPECT_IS_OK(ret); 1111 if (ret.isOk()) { 1112 drain = ret; 1113 } 1114 } 1115 bool pause = false; 1116 bool resume = false; 1117 bool drain = false; 1118 }; 1119 1120 TEST_P(OutputStreamTest, SupportsPauseAndResumeAndDrain) { 1121 doc::test( 1122 "Implementation must expose pause, resume and drain capabilities"); 1123 Capability(stream.get()); 1124 } 1125 1126 template <class Value> 1127 static void checkInvalidStateOr0(Result res, Value value) { 1128 switch (res) { 1129 case Result::INVALID_STATE: 1130 break; 1131 case Result::OK: 1132 ASSERT_EQ(0U, value); 1133 break; 1134 default: 1135 FAIL() << "Unexpected result " << toString(res); 1136 } 1137 } 1138 1139 TEST_P(OutputStreamTest, GetRenderPosition) { 1140 doc::test("A new stream render position should be 0 or INVALID_STATE"); 1141 uint32_t dspFrames; 1142 ASSERT_OK(stream->getRenderPosition(returnIn(res, dspFrames))); 1143 if (res == Result::NOT_SUPPORTED) { 1144 doc::partialTest("getRenderPosition is not supported"); 1145 return; 1146 } 1147 checkInvalidStateOr0(res, dspFrames); 1148 } 1149 1150 TEST_P(OutputStreamTest, GetNextWriteTimestamp) { 1151 doc::test("A new stream next write timestamp should be 0 or INVALID_STATE"); 1152 uint64_t timestampUs; 1153 ASSERT_OK(stream->getNextWriteTimestamp(returnIn(res, timestampUs))); 1154 if (res == Result::NOT_SUPPORTED) { 1155 doc::partialTest("getNextWriteTimestamp is not supported"); 1156 return; 1157 } 1158 checkInvalidStateOr0(res, timestampUs); 1159 } 1160 1161 /** Stub implementation of out stream callback. */ 1162 class MockOutCallbacks : public IStreamOutCallback { 1163 Return<void> onWriteReady() override { return {}; } 1164 Return<void> onDrainReady() override { return {}; } 1165 Return<void> onError() override { return {}; } 1166 }; 1167 1168 static bool isAsyncModeSupported(IStreamOut* stream) { 1169 auto res = stream->setCallback(new MockOutCallbacks); 1170 stream->clearCallback(); // try to restore the no callback state, ignore 1171 // any error 1172 auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED}; 1173 EXPECT_RESULT(okOrNotSupported, res); 1174 return res.isOk() ? res == Result::OK : false; 1175 } 1176 1177 TEST_P(OutputStreamTest, SetCallback) { 1178 doc::test( 1179 "If supported, registering callback for async operation should never " 1180 "fail"); 1181 if (!isAsyncModeSupported(stream.get())) { 1182 doc::partialTest("The stream does not support async operations"); 1183 return; 1184 } 1185 ASSERT_OK(stream->setCallback(new MockOutCallbacks)); 1186 ASSERT_OK(stream->setCallback(new MockOutCallbacks)); 1187 } 1188 1189 TEST_P(OutputStreamTest, clearCallback) { 1190 doc::test( 1191 "If supported, clearing a callback to go back to sync operation should " 1192 "not fail"); 1193 if (!isAsyncModeSupported(stream.get())) { 1194 doc::partialTest("The stream does not support async operations"); 1195 return; 1196 } 1197 // TODO: Clarify if clearing a non existing callback should fail 1198 ASSERT_OK(stream->setCallback(new MockOutCallbacks)); 1199 ASSERT_OK(stream->clearCallback()); 1200 } 1201 1202 TEST_P(OutputStreamTest, Resume) { 1203 doc::test( 1204 "If supported, a stream should fail to resume if not previously " 1205 "paused"); 1206 if (!Capability(stream.get()).resume) { 1207 doc::partialTest("The output stream does not support resume"); 1208 return; 1209 } 1210 ASSERT_RESULT(Result::INVALID_STATE, stream->resume()); 1211 } 1212 1213 TEST_P(OutputStreamTest, Pause) { 1214 doc::test( 1215 "If supported, a stream should fail to pause if not previously " 1216 "started"); 1217 if (!Capability(stream.get()).pause) { 1218 doc::partialTest("The output stream does not support pause"); 1219 return; 1220 } 1221 ASSERT_RESULT(Result::INVALID_STATE, stream->resume()); 1222 } 1223 1224 static void testDrain(IStreamOut* stream, AudioDrain type) { 1225 if (!Capability(stream).drain) { 1226 doc::partialTest("The output stream does not support drain"); 1227 return; 1228 } 1229 ASSERT_RESULT(Result::OK, stream->drain(type)); 1230 } 1231 1232 TEST_P(OutputStreamTest, DrainAll) { 1233 doc::test("If supported, a stream should always succeed to drain"); 1234 testDrain(stream.get(), AudioDrain::ALL); 1235 } 1236 1237 TEST_P(OutputStreamTest, DrainEarlyNotify) { 1238 doc::test("If supported, a stream should always succeed to drain"); 1239 testDrain(stream.get(), AudioDrain::EARLY_NOTIFY); 1240 } 1241 1242 TEST_P(OutputStreamTest, FlushStop) { 1243 doc::test("If supported, a stream should always succeed to flush"); 1244 auto ret = stream->flush(); 1245 ASSERT_IS_OK(ret); 1246 if (ret == Result::NOT_SUPPORTED) { 1247 doc::partialTest("Flush is not supported"); 1248 return; 1249 } 1250 ASSERT_OK(ret); 1251 } 1252 1253 TEST_P(OutputStreamTest, GetPresentationPositionStop) { 1254 doc::test( 1255 "If supported, a stream should always succeed to retrieve the " 1256 "presentation position"); 1257 uint64_t frames; 1258 TimeSpec mesureTS; 1259 ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, mesureTS))); 1260 if (res == Result::NOT_SUPPORTED) { 1261 doc::partialTest("getpresentationPosition is not supported"); 1262 return; 1263 } 1264 ASSERT_EQ(0U, frames); 1265 1266 if (mesureTS.tvNSec == 0 && mesureTS.tvSec == 0) { 1267 // As the stream has never written a frame yet, 1268 // the timestamp does not really have a meaning, allow to return 0 1269 return; 1270 } 1271 1272 // Make sure the return measure is not more than 1s old. 1273 struct timespec currentTS; 1274 ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤tTS)) << errno; 1275 1276 auto toMicroSec = [](uint64_t sec, auto nsec) { 1277 return sec * 1e+6 + nsec / 1e+3; 1278 }; 1279 auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec); 1280 auto mesureTime = toMicroSec(mesureTS.tvSec, mesureTS.tvNSec); 1281 ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, 1282 mesureTime); 1283 } 1284 1285 ////////////////////////////////////////////////////////////////////////////// 1286 /////////////////////////////// PrimaryDevice //////////////////////////////// 1287 ////////////////////////////////////////////////////////////////////////////// 1288 1289 TEST_F(AudioPrimaryHidlTest, setVoiceVolume) { 1290 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]"); 1291 testUnitaryGain([](float volume) { return device->setVoiceVolume(volume); }); 1292 } 1293 1294 TEST_F(AudioPrimaryHidlTest, setMode) { 1295 doc::test( 1296 "Make sure setMode always succeeds if mode is valid " 1297 "and fails otherwise"); 1298 // Test Invalid values 1299 for (AudioMode mode : 1300 {AudioMode::INVALID, AudioMode::CURRENT, AudioMode::CNT}) { 1301 SCOPED_TRACE("mode=" + toString(mode)); 1302 ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(mode)); 1303 } 1304 // Test valid values 1305 for (AudioMode mode : 1306 {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE, 1307 AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) { 1308 SCOPED_TRACE("mode=" + toString(mode)); 1309 ASSERT_OK(device->setMode(mode)); 1310 } 1311 } 1312 1313 TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) { 1314 doc::test("Query and set the BT SCO NR&EC state"); 1315 testOptionalAccessors("BtScoNrecEnabled", {true, false, true}, 1316 &IPrimaryDevice::setBtScoNrecEnabled, 1317 &IPrimaryDevice::getBtScoNrecEnabled); 1318 } 1319 1320 TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) { 1321 doc::test("Query and set the SCO whideband state"); 1322 testOptionalAccessors("BtScoWideband", {true, false, true}, 1323 &IPrimaryDevice::setBtScoWidebandEnabled, 1324 &IPrimaryDevice::getBtScoWidebandEnabled); 1325 } 1326 1327 using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>; 1328 TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) { 1329 doc::test("Query and set the TTY mode state"); 1330 testOptionalAccessors( 1331 "TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL}, 1332 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode); 1333 } 1334 1335 TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) { 1336 doc::test("Query and set the HAC state"); 1337 testOptionalAccessors("HAC", {true, false, true}, 1338 &IPrimaryDevice::setHacEnabled, 1339 &IPrimaryDevice::getHacEnabled); 1340 } 1341 1342 ////////////////////////////////////////////////////////////////////////////// 1343 //////////////////// Clean caches on global tear down //////////////////////// 1344 ////////////////////////////////////////////////////////////////////////////// 1345 1346 int main(int argc, char** argv) { 1347 environment = new Environment; 1348 ::testing::AddGlobalTestEnvironment(environment); 1349 ::testing::InitGoogleTest(&argc, argv); 1350 int status = RUN_ALL_TESTS(); 1351 return status; 1352 } 1353