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