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