1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "VtsHalAudioVTargetTest"
18
19 #include <algorithm>
20 #include <cmath>
21 #include <cstddef>
22 #include <cstdio>
23 #include <initializer_list>
24 #include <limits>
25 #include <list>
26 #include <map>
27 #include <set>
28 #include <string>
29 #include <variant>
30 #include <vector>
31
32 #include <fcntl.h>
33 #include <unistd.h>
34
35 #include <hwbinder/IPCThreadState.h>
36
37 #include <android-base/logging.h>
38 #include <system/audio_config.h>
39
40 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
41 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
42 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
43 #include PATH(android/hardware/audio/FILE_VERSION/types.h)
44 #include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
45
46 #include <Serializer.h>
47 #include <fmq/EventFlag.h>
48 #include <fmq/MessageQueue.h>
49 #include <hidl/GtestPrinter.h>
50 #include <hidl/ServiceManagement.h>
51
52 #include <common/all-versions/VersionUtils.h>
53
54 #include "utility/AssertOk.h"
55 #include "utility/Documentation.h"
56 #include "utility/ReturnIn.h"
57 #include "utility/ValidateXml.h"
58
59 /** Provide version specific functions that are used in the generic tests */
60 #if MAJOR_VERSION == 2
61 #include "2.0/AudioPrimaryHidlHalUtils.h"
62 #elif MAJOR_VERSION >= 4
63 #include "4.0/AudioPrimaryHidlHalUtils.h"
64 #endif
65
66 using std::initializer_list;
67 using std::list;
68 using std::string;
69 using std::to_string;
70 using std::vector;
71
72 using ::android::AudioPolicyConfig;
73 using ::android::HwModule;
74 using ::android::NO_INIT;
75 using ::android::OK;
76 using ::android::sp;
77 using ::android::status_t;
78 using ::android::hardware::EventFlag;
79 using ::android::hardware::hidl_bitfield;
80 using ::android::hardware::hidl_enum_range;
81 using ::android::hardware::hidl_handle;
82 using ::android::hardware::hidl_string;
83 using ::android::hardware::hidl_vec;
84 using ::android::hardware::IPCThreadState;
85 using ::android::hardware::kSynchronizedReadWrite;
86 using ::android::hardware::MessageQueue;
87 using ::android::hardware::MQDescriptorSync;
88 using ::android::hardware::Return;
89 using ::android::hardware::audio::common::utils::EnumBitfield;
90 using ::android::hardware::audio::common::utils::mkEnumBitfield;
91 using ::android::hardware::details::toHexString;
92
93 using namespace ::android::hardware::audio::common::CPP_VERSION;
94 using namespace ::android::hardware::audio::common::test::utility;
95 using namespace ::android::hardware::audio::CPP_VERSION;
96
97 // Typical accepted results from interface methods
98 static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
99 static auto okOrNotSupportedOrInvalidArgs = {Result::OK, Result::NOT_SUPPORTED,
100 Result::INVALID_ARGUMENTS};
101 static auto okOrInvalidStateOrNotSupported = {Result::OK, Result::INVALID_STATE,
102 Result::NOT_SUPPORTED};
103 static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
104 static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
105
106 #define AUDIO_PRIMARY_HIDL_HAL_TEST
107 #include "DeviceManager.h"
108
109 class HidlTest : public ::testing::Test {
110 public:
111 virtual ~HidlTest() = default;
112 // public access to avoid annoyances when using this method in template classes
113 // derived from test classes
getDevice()114 sp<IDevice> getDevice() const {
115 return DeviceManager::getInstance().get(getFactoryName(), getDeviceName());
116 }
117
118 protected:
119 // Factory and device name getters to be overridden in subclasses.
120 virtual const std::string& getFactoryName() const = 0;
121 virtual const std::string& getDeviceName() const = 0;
122
getDevicesFactory()123 sp<IDevicesFactory> getDevicesFactory() const {
124 return DevicesFactoryManager::getInstance().get(getFactoryName());
125 }
resetDevice()126 bool resetDevice() const {
127 return DeviceManager::getInstance().reset(getFactoryName(), getDeviceName());
128 }
areAudioPatchesSupported()129 bool areAudioPatchesSupported() { return extract(getDevice()->supportsAudioPatches()); }
130
131 // Convenient member to store results
132 Result res;
133 };
134
135 //////////////////////////////////////////////////////////////////////////////
136 ////////////////////////// Audio policy configuration ////////////////////////
137 //////////////////////////////////////////////////////////////////////////////
138
139 static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
140
141 // Stringify the argument.
142 #define QUOTE(x) #x
143 #define STRINGIFY(x) QUOTE(x)
144
145 struct PolicyConfigData {
146 android::HwModuleCollection hwModules;
147 android::DeviceVector availableOutputDevices;
148 android::DeviceVector availableInputDevices;
149 sp<android::DeviceDescriptor> defaultOutputDevice;
150 };
151
152 class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
153 public:
PolicyConfig()154 PolicyConfig()
155 : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
156 defaultOutputDevice) {
157 for (const auto& location : android::audio_get_configuration_paths()) {
158 std::string path = location + '/' + kConfigFileName;
159 if (access(path.c_str(), F_OK) == 0) {
160 mFilePath = path;
161 break;
162 }
163 }
164 mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
165 if (mStatus == OK) {
166 mPrimaryModule = getHwModules().getModuleFromName(DeviceManager::kPrimaryDevice);
167 // Available devices are not 'attached' to modules at this moment.
168 // Need to go over available devices and find their module.
169 for (const auto& device : availableOutputDevices) {
170 for (const auto& module : hwModules) {
171 if (module->getDeclaredDevices().indexOf(device) >= 0) {
172 mModulesWithDevicesNames.insert(module->getName());
173 break;
174 }
175 }
176 }
177 for (const auto& device : availableInputDevices) {
178 for (const auto& module : hwModules) {
179 if (module->getDeclaredDevices().indexOf(device) >= 0) {
180 mModulesWithDevicesNames.insert(module->getName());
181 break;
182 }
183 }
184 }
185 }
186 }
getStatus()187 status_t getStatus() const { return mStatus; }
getError()188 std::string getError() const {
189 if (mFilePath.empty()) {
190 return std::string{"Could not find "} + kConfigFileName +
191 " file in: " + testing::PrintToString(android::audio_get_configuration_paths());
192 } else {
193 return "Invalid config file: " + mFilePath;
194 }
195 }
getFilePath()196 const std::string& getFilePath() const { return mFilePath; }
getModuleFromName(const std::string & name)197 sp<const HwModule> getModuleFromName(const std::string& name) const {
198 return getHwModules().getModuleFromName(name.c_str());
199 }
getPrimaryModule()200 sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
getModulesWithDevicesNames()201 const std::set<std::string>& getModulesWithDevicesNames() const {
202 return mModulesWithDevicesNames;
203 }
204
205 private:
206 status_t mStatus = NO_INIT;
207 std::string mFilePath;
208 sp<HwModule> mPrimaryModule = nullptr;
209 std::set<std::string> mModulesWithDevicesNames;
210 };
211
212 // Cached policy config after parsing for faster test startup
getCachedPolicyConfig()213 const PolicyConfig& getCachedPolicyConfig() {
214 static std::unique_ptr<PolicyConfig> policyConfig = [] {
215 auto config = std::make_unique<PolicyConfig>();
216 return config;
217 }();
218 return *policyConfig;
219 }
220
221 //////////////////////////////////////////////////////////////////////////////
222 //////////////////// Test parameter types and definitions ////////////////////
223 //////////////////////////////////////////////////////////////////////////////
224
225 enum { PARAM_FACTORY_NAME, PARAM_DEVICE_NAME };
226 using DeviceParameter = std::tuple<std::string, std::string>;
227
DeviceParameterToString(const::testing::TestParamInfo<DeviceParameter> & info)228 static inline std::string DeviceParameterToString(
229 const ::testing::TestParamInfo<DeviceParameter>& info) {
230 const auto& deviceName = std::get<PARAM_DEVICE_NAME>(info.param);
231 const auto factoryName =
232 ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
233 std::get<PARAM_FACTORY_NAME>(info.param), info.index});
234 return !deviceName.empty() ? factoryName + "_" + deviceName : factoryName;
235 }
236
getDeviceParameters()237 const std::vector<DeviceParameter>& getDeviceParameters() {
238 static std::vector<DeviceParameter> parameters = [] {
239 std::vector<DeviceParameter> result;
240 const auto factories =
241 ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
242 const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
243 result.reserve(devices.size());
244 for (const auto& factoryName : factories) {
245 for (const auto& deviceName : devices) {
246 if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) {
247 result.emplace_back(factoryName, deviceName);
248 }
249 }
250 }
251 return result;
252 }();
253 return parameters;
254 }
255
getDeviceParametersForFactoryTests()256 const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
257 static std::vector<DeviceParameter> parameters = [] {
258 std::vector<DeviceParameter> result;
259 const auto factories =
260 ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
261 for (const auto& factoryName : factories) {
262 result.emplace_back(factoryName,
263 DeviceManager::getInstance().getPrimary(factoryName) != nullptr
264 ? DeviceManager::kPrimaryDevice
265 : "");
266 }
267 return result;
268 }();
269 return parameters;
270 }
271
getDeviceParametersForPrimaryDeviceTests()272 const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
273 static std::vector<DeviceParameter> parameters = [] {
274 std::vector<DeviceParameter> result;
275 const auto primary = std::find_if(
276 getDeviceParameters().begin(), getDeviceParameters().end(), [](const auto& elem) {
277 return std::get<PARAM_DEVICE_NAME>(elem) == DeviceManager::kPrimaryDevice;
278 });
279 if (primary != getDeviceParameters().end()) result.push_back(*primary);
280 return result;
281 }();
282 return parameters;
283 }
284
285 class AudioHidlTestWithDeviceParameter : public HidlTest,
286 public ::testing::WithParamInterface<DeviceParameter> {
287 protected:
getFactoryName()288 const std::string& getFactoryName() const override {
289 return std::get<PARAM_FACTORY_NAME>(GetParam());
290 }
getDeviceName()291 const std::string& getDeviceName() const override {
292 return std::get<PARAM_DEVICE_NAME>(GetParam());
293 }
294 };
295
TEST(CheckConfig,audioPolicyConfigurationValidation)296 TEST(CheckConfig, audioPolicyConfigurationValidation) {
297 auto deviceParameters = getDeviceParametersForFactoryTests();
298 if (deviceParameters.size() == 0) {
299 GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no device parameter "
300 "is found.";
301 }
302 RecordProperty("description",
303 "Verify that the audio policy configuration file "
304 "is valid according to the schema");
305
306 const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
307 EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
308 android::audio_get_configuration_paths(), xsd);
309 }
310
311 class AudioPolicyConfigTest : public AudioHidlTestWithDeviceParameter {
312 public:
SetUp()313 void SetUp() override {
314 ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base
315 auto& policyConfig = getCachedPolicyConfig();
316 ASSERT_EQ(0, policyConfig.getStatus()) << policyConfig.getError();
317 }
318 };
319
TEST_P(AudioPolicyConfigTest,LoadAudioPolicyXMLConfiguration)320 TEST_P(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) {
321 doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)");
322 }
323
TEST_P(AudioPolicyConfigTest,HasPrimaryModule)324 TEST_P(AudioPolicyConfigTest, HasPrimaryModule) {
325 auto& policyConfig = getCachedPolicyConfig();
326 ASSERT_TRUE(policyConfig.getPrimaryModule() != nullptr)
327 << "Could not find primary module in configuration file: "
328 << policyConfig.getFilePath();
329 }
330
331 INSTANTIATE_TEST_CASE_P(AudioHidl, AudioPolicyConfigTest,
332 ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
333 &DeviceParameterToString);
334
335 //////////////////////////////////////////////////////////////////////////////
336 ////////////////////// getService audio_devices_factory //////////////////////
337 //////////////////////////////////////////////////////////////////////////////
338
339 // Test audio devices factory
340 class AudioHidlTest : public AudioHidlTestWithDeviceParameter {
341 public:
SetUp()342 void SetUp() override {
343 ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base
344 ASSERT_TRUE(getDevicesFactory() != nullptr);
345 }
346 };
347
TEST_P(AudioHidlTest,GetAudioDevicesFactoryService)348 TEST_P(AudioHidlTest, GetAudioDevicesFactoryService) {
349 doc::test("Test the getService");
350 }
351
TEST_P(AudioHidlTest,OpenDeviceInvalidParameter)352 TEST_P(AudioHidlTest, OpenDeviceInvalidParameter) {
353 doc::test("Test passing an invalid parameter to openDevice");
354 Result result;
355 sp<IDevice> device;
356 #if MAJOR_VERSION == 2
357 auto invalidDevice = IDevicesFactory::Device(-1);
358 #elif MAJOR_VERSION >= 4
359 auto invalidDevice = "Non existing device";
360 #endif
361 ASSERT_OK(getDevicesFactory()->openDevice(invalidDevice, returnIn(result, device)));
362 ASSERT_EQ(Result::INVALID_ARGUMENTS, result);
363 ASSERT_TRUE(device == nullptr);
364 }
365
366 INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest,
367 ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
368 &DeviceParameterToString);
369
370 //////////////////////////////////////////////////////////////////////////////
371 /////////////////////////////// openDevice ///////////////////////////////////
372 //////////////////////////////////////////////////////////////////////////////
373
374 // Test all audio devices
375 class AudioHidlDeviceTest : public AudioHidlTest {
376 public:
SetUp()377 void SetUp() override {
378 ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base
379 ASSERT_TRUE(getDevice() != nullptr);
380 }
381 };
382
TEST_P(AudioHidlDeviceTest,OpenDevice)383 TEST_P(AudioHidlDeviceTest, OpenDevice) {
384 doc::test("Test openDevice (called during setup)");
385 }
386
TEST_P(AudioHidlDeviceTest,Init)387 TEST_P(AudioHidlDeviceTest, Init) {
388 doc::test("Test that the audio hal initialized correctly");
389 ASSERT_OK(getDevice()->initCheck());
390 }
391
392 INSTANTIATE_TEST_CASE_P(AudioHidlDevice, AudioHidlDeviceTest,
393 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
394
395 //////////////////////////////////////////////////////////////////////////////
396 /////////////////////////////// openDevice primary ///////////////////////////
397 //////////////////////////////////////////////////////////////////////////////
398
399 // Test the primary device
400 class AudioPrimaryHidlTest : public AudioHidlDeviceTest {
401 public:
SetUp()402 void SetUp() override {
403 ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp()); // setup base
404 ASSERT_TRUE(getDevice() != nullptr);
405 }
406
407 // public access to avoid annoyances when using this method in template classes
408 // derived from test classes
getDevice()409 sp<IPrimaryDevice> getDevice() const {
410 return DeviceManager::getInstance().getPrimary(getFactoryName());
411 }
412 };
413
TEST_P(AudioPrimaryHidlTest,OpenPrimaryDevice)414 TEST_P(AudioPrimaryHidlTest, OpenPrimaryDevice) {
415 doc::test("Test openPrimaryDevice (called during setup)");
416 }
417
418 INSTANTIATE_TEST_CASE_P(AudioPrimaryHidl, AudioPrimaryHidlTest,
419 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
420 &DeviceParameterToString);
421
422 //////////////////////////////////////////////////////////////////////////////
423 ///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
424 //////////////////////////////////////////////////////////////////////////////
425
426 template <class Property, class BaseTestClass = AudioHidlDeviceTest>
427 class AccessorHidlTest : public BaseTestClass {
428 protected:
429 enum Optionality { REQUIRED, OPTIONAL };
430 struct Initial { // Initial property value
valueInitial431 Initial(Property value, Optionality check = REQUIRED) : value(value), check(check) {}
432 Property value;
433 Optionality check; // If this initial value should be checked
434 };
435 using BaseTestClass::res;
436 /** Test a property getter and setter.
437 * The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
438 */
439 template <Optionality optionality = REQUIRED, class IUTGetter, class Getter, class Setter>
440 void testAccessors(IUTGetter iutGetter, const string& propertyName,
441 const Initial expectedInitial, list<Property> valuesToTest, Setter setter,
442 Getter getter, const vector<Property>& invalidValues = {}) {
443 const auto expectedResults = {Result::OK,
444 optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
445
446 Property initialValue = expectedInitial.value;
447 ASSERT_OK(((this->*iutGetter)().get()->*getter)(returnIn(res, initialValue)));
448 ASSERT_RESULT(expectedResults, res);
449 if (res == Result::OK && expectedInitial.check == REQUIRED) {
450 EXPECT_EQ(expectedInitial.value, initialValue);
451 }
452
453 valuesToTest.push_front(expectedInitial.value);
454 valuesToTest.push_back(initialValue);
455 for (Property setValue : valuesToTest) {
456 SCOPED_TRACE("Test " + propertyName + " getter and setter for " +
457 testing::PrintToString(setValue));
458 auto ret = ((this->*iutGetter)().get()->*setter)(setValue);
459 ASSERT_RESULT(expectedResults, ret);
460 if (ret == Result::NOT_SUPPORTED) {
461 doc::partialTest(propertyName + " setter is not supported");
462 break;
463 }
464 Property getValue;
465 // Make sure the getter returns the same value just set
466 ASSERT_OK(((this->*iutGetter)().get()->*getter)(returnIn(res, getValue)));
467 ASSERT_RESULT(expectedResults, res);
468 if (res == Result::NOT_SUPPORTED) {
469 doc::partialTest(propertyName + " getter is not supported");
470 continue;
471 }
472 EXPECT_EQ(setValue, getValue);
473 }
474
475 for (Property invalidValue : invalidValues) {
476 SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
477 testing::PrintToString(invalidValue));
478 EXPECT_RESULT(invalidArgsOrNotSupported,
479 ((this->*iutGetter)().get()->*setter)(invalidValue));
480 }
481
482 // Restore initial value
483 EXPECT_RESULT(expectedResults, ((this->*iutGetter)().get()->*setter)(initialValue));
484 }
485 template <Optionality optionality = REQUIRED, class Getter, class Setter>
486 void testAccessors(const string& propertyName, const Initial expectedInitial,
487 list<Property> valuesToTest, Setter setter, Getter getter,
488 const vector<Property>& invalidValues = {}) {
489 testAccessors<optionality>(&BaseTestClass::getDevice, propertyName, expectedInitial,
490 valuesToTest, setter, getter, invalidValues);
491 }
492 };
493
494 using BoolAccessorHidlTest = AccessorHidlTest<bool>;
495 using BoolAccessorPrimaryHidlTest = AccessorHidlTest<bool, AudioPrimaryHidlTest>;
496
TEST_P(BoolAccessorHidlTest,MicMuteTest)497 TEST_P(BoolAccessorHidlTest, MicMuteTest) {
498 doc::test("Check that the mic can be muted and unmuted");
499 testAccessors<OPTIONAL>("mic mute", Initial{false}, {true}, &IDevice::setMicMute,
500 &IDevice::getMicMute);
501 // TODO: check that the mic is really muted (all sample are 0)
502 }
503
TEST_P(BoolAccessorHidlTest,MasterMuteTest)504 TEST_P(BoolAccessorHidlTest, MasterMuteTest) {
505 doc::test("If master mute is supported, try to mute and unmute the master output");
506 testAccessors<OPTIONAL>("master mute", Initial{false}, {true}, &IDevice::setMasterMute,
507 &IDevice::getMasterMute);
508 // TODO: check that the master volume is really muted
509 }
510
511 INSTANTIATE_TEST_CASE_P(BoolAccessorHidl, BoolAccessorHidlTest,
512 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
513 INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest,
514 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
515 &DeviceParameterToString);
516
517 using FloatAccessorHidlTest = AccessorHidlTest<float>;
TEST_P(FloatAccessorHidlTest,MasterVolumeTest)518 TEST_P(FloatAccessorHidlTest, MasterVolumeTest) {
519 doc::test("Test the master volume if supported");
520 testAccessors<OPTIONAL>(
521 "master volume", Initial{1}, {0, 0.5}, &IDevice::setMasterVolume, &IDevice::getMasterVolume,
522 {-0.1, 1.1, NAN, INFINITY, -INFINITY, 1 + std::numeric_limits<float>::epsilon()});
523 // TODO: check that the master volume is really changed
524 }
525
526 INSTANTIATE_TEST_CASE_P(FloatAccessorHidl, FloatAccessorHidlTest,
527 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
528
529 //////////////////////////////////////////////////////////////////////////////
530 //////////////////////////////// AudioPatches ////////////////////////////////
531 //////////////////////////////////////////////////////////////////////////////
532
533 class AudioPatchHidlTest : public AudioHidlDeviceTest {
534 public:
SetUp()535 void SetUp() override {
536 ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp()); // setup base
537 if (!areAudioPatchesSupported()) {
538 GTEST_SKIP() << "Audio patches are not supported";
539 }
540 }
541 };
542
TEST_P(AudioPatchHidlTest,AudioPatches)543 TEST_P(AudioPatchHidlTest, AudioPatches) {
544 doc::test("Test if audio patches are supported");
545 // TODO: test audio patches
546 }
547
548 INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest,
549 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
550
551 // Nesting a tuple in another tuple allows to use GTest Combine function to generate
552 // all combinations of devices and configs.
553 enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
554 enum { INDEX_INPUT, INDEX_OUTPUT };
555 using DeviceConfigParameter =
556 std::tuple<DeviceParameter, AudioConfig, std::variant<AudioInputFlag, AudioOutputFlag>>;
557
558 #if MAJOR_VERSION >= 6
559 const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters();
560 const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters();
561 #endif
562
563 #if MAJOR_VERSION >= 4
SanitizeStringForGTestName(const string & s)564 static string SanitizeStringForGTestName(const string& s) {
565 string result = s;
566 for (size_t i = 0; i < result.size(); i++) {
567 // gtest test names must only contain alphanumeric characters
568 if (!std::isalnum(result[i])) result[i] = '_';
569 }
570 return result;
571 }
572 #endif
573
574 /** Generate a test name based on an audio config.
575 *
576 * As the only parameter changing are channel mask and sample rate,
577 * only print those ones in the test name.
578 */
DeviceConfigParameterToString(const testing::TestParamInfo<DeviceConfigParameter> & info)579 static string DeviceConfigParameterToString(
580 const testing::TestParamInfo<DeviceConfigParameter>& info) {
581 const AudioConfig& config = std::get<PARAM_CONFIG>(info.param);
582 const auto deviceName = DeviceParameterToString(::testing::TestParamInfo<DeviceParameter>{
583 std::get<PARAM_DEVICE>(info.param), info.index});
584 return (deviceName.empty() ? "" : deviceName + "_") + to_string(info.index) + "__" +
585 to_string(config.sampleRateHz) + "_" +
586 // "MONO" is more clear than "FRONT_LEFT"
587 ((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
588 config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO))
589 ? "MONO"
590 #if MAJOR_VERSION == 2
591 : ::testing::PrintToString(config.channelMask)
592 #elif MAJOR_VERSION >= 4
593 // In V4 and above the channel mask is a bitfield.
594 // Printing its value using HIDL's toString for a bitfield emits a lot of extra
595 // text due to overlapping constant values. Instead, we print the bitfield value
596 // as if it was a single value + its hex representation
597 : SanitizeStringForGTestName(
598 ::testing::PrintToString(AudioChannelMask(config.channelMask)) + "_" +
599 toHexString(config.channelMask))
600 #endif
601 ) +
602 "_" +
603 #if MAJOR_VERSION == 2
604 std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
605 std::get<PARAM_FLAGS>(info.param));
606 #elif MAJOR_VERSION >= 4
607 SanitizeStringForGTestName(std::visit(
608 [](auto&& arg) -> std::string {
609 using T = std::decay_t<decltype(arg)>;
610 // Need to use FQN of toString to avoid confusing the compiler
611 return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
612 hidl_bitfield<T>(arg));
613 },
614 std::get<PARAM_FLAGS>(info.param)));
615 #endif
616 }
617
618 class AudioHidlTestWithDeviceConfigParameter
619 : public HidlTest,
620 public ::testing::WithParamInterface<DeviceConfigParameter> {
621 protected:
SetUp()622 void SetUp() override {
623 ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base
624 ASSERT_TRUE(getDevicesFactory() != nullptr);
625 ASSERT_TRUE(getDevice() != nullptr);
626 }
getFactoryName()627 const std::string& getFactoryName() const override {
628 return std::get<PARAM_FACTORY_NAME>(std::get<PARAM_DEVICE>(GetParam()));
629 }
getDeviceName()630 const std::string& getDeviceName() const override {
631 return std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(GetParam()));
632 }
getConfig()633 const AudioConfig& getConfig() const { return std::get<PARAM_CONFIG>(GetParam()); }
634 #if MAJOR_VERSION == 2
getInputFlags()635 AudioInputFlag getInputFlags() const {
636 return std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam()));
637 }
getOutputFlags()638 AudioOutputFlag getOutputFlags() const {
639 return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
640 }
641 #elif MAJOR_VERSION >= 4
getInputFlags()642 hidl_bitfield<AudioInputFlag> getInputFlags() const {
643 return hidl_bitfield<AudioInputFlag>(
644 std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
645 }
getOutputFlags()646 hidl_bitfield<AudioOutputFlag> getOutputFlags() const {
647 return hidl_bitfield<AudioOutputFlag>(
648 std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
649 }
650 #endif
651 };
652
653 #include "ConfigHelper.h"
654
655 //////////////////////////////////////////////////////////////////////////////
656 ///////////////////////////// getInputBufferSize /////////////////////////////
657 //////////////////////////////////////////////////////////////////////////////
658
659 // FIXME: execute input test only if platform declares
660 // android.hardware.microphone
661 // how to get this value ? is it a property ???
662
663 class AudioCaptureConfigTest : public AudioHidlTestWithDeviceConfigParameter {
664 protected:
inputBufferSizeTest(const AudioConfig & audioConfig,bool supportRequired)665 void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
666 uint64_t bufferSize;
667 ASSERT_OK(getDevice()->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
668
669 switch (res) {
670 case Result::INVALID_ARGUMENTS:
671 EXPECT_FALSE(supportRequired);
672 break;
673 case Result::OK:
674 // Check that the buffer is of a sane size
675 // For now only that it is > 0
676 EXPECT_GT(bufferSize, uint64_t(0));
677 break;
678 default:
679 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
680 }
681 }
682 };
683
684 // Test that the required capture config and those declared in the policy are
685 // indeed supported
686 class RequiredInputBufferSizeTest : public AudioCaptureConfigTest {};
TEST_P(RequiredInputBufferSizeTest,RequiredInputBufferSizeTest)687 TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
688 doc::test(
689 "Input buffer size must be retrievable for a format with required "
690 "support.");
691 inputBufferSizeTest(getConfig(), true);
692 }
693
694 // Test that the recommended capture config are supported or lead to a
695 // INVALID_ARGUMENTS return
696 class OptionalInputBufferSizeTest : public AudioCaptureConfigTest {};
TEST_P(OptionalInputBufferSizeTest,OptionalInputBufferSizeTest)697 TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
698 doc::test(
699 "Input buffer size should be retrievable for a format with recommended "
700 "support.");
701 inputBufferSizeTest(getConfig(), false);
702 }
703
704 #if MAJOR_VERSION <= 5
705 // For V2..5 test the primary device according to CDD requirements.
706 INSTANTIATE_TEST_CASE_P(
707 RequiredInputBufferSize, RequiredInputBufferSizeTest,
708 ::testing::Combine(
709 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
710 ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()),
711 ::testing::Values(AudioInputFlag::NONE)),
712 &DeviceConfigParameterToString);
713 INSTANTIATE_TEST_CASE_P(
714 RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
715 ::testing::Combine(
716 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
717 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
718 ::testing::Values(AudioInputFlag::NONE)),
719 &DeviceConfigParameterToString);
720 #elif MAJOR_VERSION >= 6
721 INSTANTIATE_TEST_CASE_P(SupportedInputBufferSize, RequiredInputBufferSizeTest,
722 ::testing::ValuesIn(getInputDeviceConfigParameters()),
723 &DeviceConfigParameterToString);
724 #endif
725
726 //////////////////////////////////////////////////////////////////////////////
727 /////////////////////////////// setScreenState ///////////////////////////////
728 //////////////////////////////////////////////////////////////////////////////
729
TEST_P(AudioHidlDeviceTest,setScreenState)730 TEST_P(AudioHidlDeviceTest, setScreenState) {
731 doc::test("Check that the hal can receive the screen state");
732 for (bool turnedOn : {false, true, true, false, false}) {
733 ASSERT_RESULT(okOrNotSupported, getDevice()->setScreenState(turnedOn));
734 }
735 }
736
737 //////////////////////////////////////////////////////////////////////////////
738 //////////////////////////// {get,set}Parameters /////////////////////////////
739 //////////////////////////////////////////////////////////////////////////////
740
TEST_P(AudioHidlDeviceTest,getParameters)741 TEST_P(AudioHidlDeviceTest, getParameters) {
742 doc::test("Check that the hal can set and get parameters");
743 hidl_vec<ParameterValue> context;
744 hidl_vec<hidl_string> keys;
745 hidl_vec<ParameterValue> values;
746 ASSERT_OK(Parameters::get(getDevice(), keys, returnIn(res, values)));
747 ASSERT_RESULT(okOrNotSupported, res);
748 ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values));
749 values.resize(0);
750 ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values));
751 }
752
753 //////////////////////////////////////////////////////////////////////////////
754 //////////////////////////////// debugDebug //////////////////////////////////
755 //////////////////////////////////////////////////////////////////////////////
756
757 template <class DebugDump>
testDebugDump(DebugDump debugDump)758 static void testDebugDump(DebugDump debugDump) {
759 // File descriptors to our pipe. fds[0] corresponds to the read end and
760 // fds[1] to the write end.
761 int fds[2];
762 ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
763
764 // Make sure that the pipe is at least 1 MB in size. The test process runs
765 // in su domain, so it should be safe to make this call.
766 fcntl(fds[0], F_SETPIPE_SZ, 1 << 20);
767
768 // Wrap the temporary file file descriptor in a native handle
769 auto* nativeHandle = native_handle_create(1, 0);
770 ASSERT_NE(nullptr, nativeHandle);
771 nativeHandle->data[0] = fds[1];
772
773 // Wrap this native handle in a hidl handle
774 hidl_handle handle;
775 handle.setTo(nativeHandle, false /*take ownership*/);
776
777 ASSERT_OK(debugDump(handle));
778
779 // Check that at least one bit was written by the hal
780 // TODO: debugDump does not return a Result.
781 // This mean that the hal can not report that it not implementing the
782 // function.
783 char buff;
784 if (read(fds[0], &buff, 1) != 1) {
785 doc::note("debugDump does not seem implemented");
786 }
787 EXPECT_EQ(0, close(fds[0])) << errno;
788 EXPECT_EQ(0, close(fds[1])) << errno;
789 }
790
TEST_P(AudioHidlDeviceTest,DebugDump)791 TEST_P(AudioHidlDeviceTest, DebugDump) {
792 doc::test("Check that the hal can dump its state without error");
793 testDebugDump([this](const auto& handle) { return dump(getDevice(), handle); });
794 }
795
TEST_P(AudioHidlDeviceTest,DebugDumpInvalidArguments)796 TEST_P(AudioHidlDeviceTest, DebugDumpInvalidArguments) {
797 doc::test("Check that the hal dump doesn't crash on invalid arguments");
798 ASSERT_OK(dump(getDevice(), hidl_handle()));
799 }
800
801 //////////////////////////////////////////////////////////////////////////////
802 ////////////////////////// open{Output,Input}Stream //////////////////////////
803 //////////////////////////////////////////////////////////////////////////////
804
805 // This class is also used by some device tests.
806 template <class Stream>
807 class StreamHelper {
808 public:
809 // StreamHelper doesn't own the stream, this is for simpler stream lifetime management.
StreamHelper(sp<Stream> & stream)810 explicit StreamHelper(sp<Stream>& stream) : mStream(stream) {}
811 template <class Open>
open(Open openStream,const AudioConfig & config,Result * res,AudioConfig * suggestedConfigPtr)812 void open(Open openStream, const AudioConfig& config, Result* res,
813 AudioConfig* suggestedConfigPtr) {
814 // FIXME: Open a stream without an IOHandle
815 // This is not required to be accepted by hal implementations
816 AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
817 AudioConfig suggestedConfig{};
818 bool retryWithSuggestedConfig = true;
819 if (suggestedConfigPtr == nullptr) {
820 suggestedConfigPtr = &suggestedConfig;
821 retryWithSuggestedConfig = false;
822 }
823 ASSERT_OK(openStream(ioHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
824 switch (*res) {
825 case Result::OK:
826 ASSERT_TRUE(mStream != nullptr);
827 *suggestedConfigPtr = config;
828 break;
829 case Result::INVALID_ARGUMENTS:
830 ASSERT_TRUE(mStream == nullptr);
831 if (retryWithSuggestedConfig) {
832 AudioConfig suggestedConfigRetry;
833 ASSERT_OK(openStream(ioHandle, *suggestedConfigPtr,
834 returnIn(*res, mStream, suggestedConfigRetry)));
835 ASSERT_OK(*res);
836 ASSERT_TRUE(mStream != nullptr);
837 }
838 break;
839 default:
840 FAIL() << "Invalid return status: " << ::testing::PrintToString(*res);
841 }
842 }
close(bool clear,Result * res)843 void close(bool clear, Result* res) {
844 auto ret = mStream->close();
845 EXPECT_TRUE(ret.isOk());
846 *res = ret;
847 if (clear) {
848 mStream.clear();
849 #if MAJOR_VERSION <= 5
850 // FIXME: there is no way to know when the remote IStream is being destroyed
851 // Binder does not support testing if an object is alive, thus
852 // wait for 100ms to let the binder destruction propagates and
853 // the remote device has the time to be destroyed.
854 // flushCommand makes sure all local command are sent, thus should reduce
855 // the latency between local and remote destruction.
856 IPCThreadState::self()->flushCommands();
857 usleep(100 * 1000);
858 #endif
859 }
860 }
861
862 private:
863 sp<Stream>& mStream;
864 };
865
866 template <class Stream>
867 class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
868 public:
869 // public access to avoid annoyances when using this method in template classes
870 // derived from test classes
getStream()871 sp<Stream> getStream() const { return stream; }
872
873 protected:
OpenStreamTest()874 OpenStreamTest() : AudioHidlTestWithDeviceConfigParameter(), helper(stream) {}
875 template <class Open>
testOpen(Open openStream,const AudioConfig & config)876 void testOpen(Open openStream, const AudioConfig& config) {
877 // TODO: only allow failure for RecommendedPlaybackAudioConfig
878 ASSERT_NO_FATAL_FAILURE(helper.open(openStream, config, &res, &audioConfig));
879 open = true;
880 }
881
882 Result closeStream(bool clear = true) {
883 open = false;
884 helper.close(clear, &res);
885 return res;
886 }
887
888 private:
TearDown()889 void TearDown() override {
890 if (open) {
891 ASSERT_OK(closeStream());
892 }
893 AudioHidlTestWithDeviceConfigParameter::TearDown();
894 }
895
896 protected:
897 AudioConfig audioConfig;
898 DeviceAddress address = {};
899 sp<Stream> stream;
900 StreamHelper<Stream> helper;
901 bool open = false;
902 };
903
904 ////////////////////////////// openOutputStream //////////////////////////////
905
906 class OutputStreamTest : public OpenStreamTest<IStreamOut> {
SetUp()907 void SetUp() override {
908 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
909 address.device = AudioDevice::OUT_DEFAULT;
910 const AudioConfig& config = getConfig();
911 auto flags = getOutputFlags();
912 testOpen(
913 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
914 #if MAJOR_VERSION == 2
915 return getDevice()->openOutputStream(handle, address, config, flags, cb);
916 #elif MAJOR_VERSION >= 4
917 return getDevice()->openOutputStream(handle, address, config, flags,
918 initMetadata, cb);
919 #endif
920 },
921 config);
922 }
923 #if MAJOR_VERSION >= 4
924
925 protected:
926 const SourceMetadata initMetadata = {
927 { { AudioUsage::MEDIA,
928 AudioContentType::MUSIC,
929 1 /* gain */ } }};
930 #endif
931 };
TEST_P(OutputStreamTest,OpenOutputStreamTest)932 TEST_P(OutputStreamTest, OpenOutputStreamTest) {
933 doc::test(
934 "Check that output streams can be open with the required and "
935 "recommended config");
936 // Open done in SetUp
937 }
938
939 #if MAJOR_VERSION <= 5
940 // For V2..5 test the primary device according to CDD requirements.
941 INSTANTIATE_TEST_CASE_P(
942 RequiredOutputStreamConfigSupport, OutputStreamTest,
943 ::testing::Combine(
944 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
945 ::testing::ValuesIn(ConfigHelper::getRequiredSupportPlaybackAudioConfig()),
946 ::testing::Values(AudioOutputFlag::NONE)),
947 &DeviceConfigParameterToString);
948 INSTANTIATE_TEST_CASE_P(
949 RecommendedOutputStreamConfigSupport, OutputStreamTest,
950 ::testing::Combine(
951 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
952 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportPlaybackAudioConfig()),
953 ::testing::Values(AudioOutputFlag::NONE)),
954 &DeviceConfigParameterToString);
955 #elif MAJOR_VERSION >= 6
956 // For V6 and above test according to the audio policy manager configuration.
957 // This is more correct as CDD is written from the apps perspective.
958 // Audio system provides necessary format conversions for missing configurations.
959 INSTANTIATE_TEST_CASE_P(DeclaredOutputStreamConfigSupport, OutputStreamTest,
960 ::testing::ValuesIn(getOutputDeviceConfigParameters()),
961 &DeviceConfigParameterToString);
962 #endif
963
964 ////////////////////////////// openInputStream //////////////////////////////
965
966 class InputStreamTest : public OpenStreamTest<IStreamIn> {
SetUp()967 void SetUp() override {
968 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
969 address.device = AudioDevice::IN_DEFAULT;
970 const AudioConfig& config = getConfig();
971 auto flags = getInputFlags();
972 testOpen(
973 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
974 return getDevice()->openInputStream(handle, address, config, flags,
975 initMetadata, cb);
976 },
977 config);
978 }
979
980 protected:
981 #if MAJOR_VERSION == 2
982 const AudioSource initMetadata = AudioSource::DEFAULT;
983 #elif MAJOR_VERSION >= 4
984 const SinkMetadata initMetadata = {{{.source = AudioSource::DEFAULT, .gain = 1}}};
985 #endif
986 };
987
TEST_P(InputStreamTest,OpenInputStreamTest)988 TEST_P(InputStreamTest, OpenInputStreamTest) {
989 doc::test(
990 "Check that input streams can be open with the required and "
991 "recommended config");
992 // Open done in setup
993 }
994 #if MAJOR_VERSION <= 5
995 // For V2..5 test the primary device according to CDD requirements.
996 INSTANTIATE_TEST_CASE_P(
997 RequiredInputStreamConfigSupport, InputStreamTest,
998 ::testing::Combine(
999 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1000 ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()),
1001 ::testing::Values(AudioInputFlag::NONE)),
1002 &DeviceConfigParameterToString);
1003 INSTANTIATE_TEST_CASE_P(
1004 RecommendedInputStreamConfigSupport, InputStreamTest,
1005 ::testing::Combine(
1006 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1007 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
1008 ::testing::Values(AudioInputFlag::NONE)),
1009 &DeviceConfigParameterToString);
1010 #elif MAJOR_VERSION >= 6
1011 // For V6 and above test according to the audio policy manager configuration.
1012 // This is more correct as CDD is written from the apps perspective.
1013 // Audio system provides necessary format conversions for missing configurations.
1014 INSTANTIATE_TEST_CASE_P(DeclaredInputStreamConfigSupport, InputStreamTest,
1015 ::testing::ValuesIn(getInputDeviceConfigParameters()),
1016 &DeviceConfigParameterToString);
1017 #endif
1018
1019 //////////////////////////////////////////////////////////////////////////////
1020 ////////////////////////////// IStream getters ///////////////////////////////
1021 //////////////////////////////////////////////////////////////////////////////
1022
1023 /* Could not find a way to write a test for two parametrized class fixure
1024 * thus use this macro do duplicate tests for Input and Output stream */
1025 #define TEST_IO_STREAM(test_name, documentation, code) \
1026 TEST_P(InputStreamTest, test_name) { \
1027 doc::test(documentation); \
1028 code; \
1029 } \
1030 TEST_P(OutputStreamTest, test_name) { \
1031 doc::test(documentation); \
1032 code; \
1033 }
1034
1035 TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
1036 ASSERT_TRUE(stream->getFrameCount().isOk()))
1037
1038 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
1039 ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
1040
1041 TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it was opened with",
1042 ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask())))
1043
1044 TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
1045 ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
1046
1047 // TODO: for now only check that the framesize is not incoherent
1048 TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
1049 ASSERT_GT(extract(stream->getFrameSize()), 0U))
1050
1051 TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it was opened with",
1052 ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize())));
1053
1054 template <class Property, class CapabilityGetter>
1055 static void testCapabilityGetter(const string& name, IStream* stream,
1056 CapabilityGetter capabilityGetter,
1057 Return<Property> (IStream::*getter)(),
1058 Return<Result> (IStream::*setter)(Property),
1059 bool currentMustBeSupported = true) {
1060 hidl_vec<Property> capabilities;
1061 auto ret = capabilityGetter(stream, capabilities);
1062 ASSERT_RESULT(okOrNotSupported, ret);
1063 bool notSupported = ret == Result::NOT_SUPPORTED;
1064 if (notSupported) {
1065 doc::partialTest(name + " is not supported");
1066 return;
1067 };
1068
1069 if (currentMustBeSupported) {
1070 ASSERT_NE(0U, capabilities.size()) << name << " must not return an empty list";
1071 Property currentValue = extract((stream->*getter)());
1072 EXPECT_TRUE(std::find(capabilities.begin(), capabilities.end(), currentValue) !=
1073 capabilities.end())
1074 << "value returned by " << name << "() = " << testing::PrintToString(currentValue)
1075 << " is not in the list of the supported ones " << toString(capabilities);
1076 }
1077
1078 // Check that all declared supported values are indeed supported
1079 for (auto capability : capabilities) {
1080 auto ret = (stream->*setter)(capability);
1081 ASSERT_TRUE(ret.isOk());
1082 if (ret == Result::NOT_SUPPORTED) {
1083 doc::partialTest("Setter is not supported");
1084 return;
1085 }
1086 ASSERT_OK(ret);
1087 ASSERT_EQ(capability, extract((stream->*getter)()));
1088 }
1089 }
1090
1091 TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
1092 testCapabilityGetter("getSupportedSampleRate", stream.get(),
1093 &GetSupported::sampleRates, &IStream::getSampleRate,
1094 &IStream::setSampleRate,
1095 // getSupportedSampleRate returns the native sampling rates,
1096 // (the sampling rates that can be played without resampling)
1097 // but other sampling rates can be supported by the HAL.
1098 false))
1099
1100 TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is declared as supported",
1101 testCapabilityGetter("getSupportedChannelMask", stream.get(),
1102 &GetSupported::channelMasks, &IStream::getChannelMask,
1103 &IStream::setChannelMask))
1104
1105 TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
1106 testCapabilityGetter("getSupportedFormat", stream.get(), &GetSupported::formats,
1107 &IStream::getFormat, &IStream::setFormat))
1108
testGetAudioProperties(IStream * stream,AudioConfig expectedConfig)1109 static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
1110 uint32_t sampleRateHz;
1111 auto mask = mkEnumBitfield<AudioChannelMask>({});
1112 AudioFormat format;
1113
1114 stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
1115
1116 // FIXME: the qcom hal it does not currently negotiate the sampleRate &
1117 // channel mask
1118 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
1119 EXPECT_EQ(expectedConfig.channelMask, mask);
1120 EXPECT_EQ(expectedConfig.format, format);
1121 }
1122
1123 TEST_IO_STREAM(GetAudioProperties,
1124 "Check that the stream audio properties == the ones it was opened with",
1125 testGetAudioProperties(stream.get(), audioConfig))
1126
1127 TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value",
1128 ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, stream->setHwAvSync(666)))
1129
checkGetNoParameter(IStream * stream,hidl_vec<hidl_string> keys,initializer_list<Result> expectedResults)1130 static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
1131 initializer_list<Result> expectedResults) {
1132 hidl_vec<ParameterValue> parameters;
1133 Result res;
1134 ASSERT_OK(Parameters::get(stream, keys, returnIn(res, parameters)));
1135 ASSERT_RESULT(expectedResults, res);
1136 if (res == Result::OK) {
1137 for (auto& parameter : parameters) {
1138 ASSERT_EQ(0U, parameter.value.size()) << toString(parameter);
1139 }
1140 }
1141 }
1142
1143 /* Get/Set parameter is intended to be an opaque channel between vendors app and
1144 * their HALs.
1145 * Thus can not be meaningfully tested.
1146 */
1147 TEST_IO_STREAM(getEmptySetParameter, "Retrieve the values of an empty set",
1148 checkGetNoParameter(stream.get(), {} /* keys */, {Result::OK}))
1149
1150 TEST_IO_STREAM(getNonExistingParameter, "Retrieve the values of an non existing parameter",
1151 checkGetNoParameter(stream.get(), {"Non existing key"} /* keys */,
1152 {Result::NOT_SUPPORTED}))
1153
1154 TEST_IO_STREAM(setEmptySetParameter, "Set the values of an empty set of parameters",
1155 ASSERT_RESULT(Result::OK, Parameters::set(stream, {})))
1156
1157 TEST_IO_STREAM(setNonExistingParameter, "Set the values of an non existing parameter",
1158 // Unfortunately, the set_parameter legacy interface did not return any
1159 // error code when a key is not supported.
1160 // To allow implementation to just wrapped the legacy one, consider OK as a
1161 // valid result for setting a non existing parameter.
1162 ASSERT_RESULT(okOrNotSupportedOrInvalidArgs,
1163 Parameters::set(stream, {{"non existing key", "0"}})))
1164
1165 TEST_IO_STREAM(DebugDump, "Check that a stream can dump its state without error",
1166 testDebugDump([this](const auto& handle) { return dump(stream, handle); }))
1167
1168 TEST_IO_STREAM(DebugDumpInvalidArguments,
1169 "Check that the stream dump doesn't crash on invalid arguments",
1170 ASSERT_OK(dump(stream, hidl_handle())))
1171
1172 //////////////////////////////////////////////////////////////////////////////
1173 ////////////////////////////// addRemoveEffect ///////////////////////////////
1174 //////////////////////////////////////////////////////////////////////////////
1175
1176 TEST_IO_STREAM(AddNonExistingEffect, "Adding a non existing effect should fail",
1177 ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->addEffect(666)))
1178 TEST_IO_STREAM(RemoveNonExistingEffect, "Removing a non existing effect should fail",
1179 ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->removeEffect(666)))
1180
1181 // TODO: positive tests
1182
1183 //////////////////////////////////////////////////////////////////////////////
1184 /////////////////////////////// Control ////////////////////////////////
1185 //////////////////////////////////////////////////////////////////////////////
1186
1187 TEST_IO_STREAM(standby, "Make sure the stream can be put in stanby",
1188 ASSERT_OK(stream->standby())) // can not fail
1189
1190 TEST_IO_STREAM(startNoMmap, "Starting a mmaped stream before mapping it should fail",
1191 ASSERT_RESULT(invalidStateOrNotSupported, stream->start()))
1192
1193 TEST_IO_STREAM(stopNoMmap, "Stopping a mmaped stream before mapping it should fail",
1194 ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
1195
1196 TEST_IO_STREAM(getMmapPositionNoMmap, "Get a stream Mmap position before mapping it should fail",
1197 ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
1198
1199 TEST_IO_STREAM(close, "Make sure a stream can be closed", ASSERT_OK(closeStream()))
1200 // clang-format off
1201 TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice",
1202 ASSERT_OK(closeStream(false /*clear*/));
1203 ASSERT_EQ(Result::INVALID_STATE, closeStream()))
1204 // clang-format on
1205
testMmapBufferOfInvalidSize(IStream * stream)1206 static void testMmapBufferOfInvalidSize(IStream* stream) {
1207 for (int32_t value : {-1, 0, std::numeric_limits<int32_t>::max()}) {
1208 MmapBufferInfo info;
1209 Result res;
1210 EXPECT_OK(stream->createMmapBuffer(value, returnIn(res, info)));
1211 EXPECT_RESULT(invalidArgsOrNotSupported, res) << "value=" << value;
1212 }
1213 }
1214
1215 TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer of invalid size must fail",
1216 testMmapBufferOfInvalidSize(stream.get()))
1217
testGetMmapPositionOfNonMmapedStream(IStream * stream)1218 static void testGetMmapPositionOfNonMmapedStream(IStream* stream) {
1219 Result res;
1220 MmapPosition position;
1221 ASSERT_OK(stream->getMmapPosition(returnIn(res, position)));
1222 ASSERT_RESULT(invalidArgsOrNotSupported, res);
1223 }
1224
1225 TEST_IO_STREAM(GetMmapPositionOfNonMmapedStream,
1226 "Retrieving the mmap position of a non mmaped stream should fail",
1227 testGetMmapPositionOfNonMmapedStream(stream.get()))
1228
1229 //////////////////////////////////////////////////////////////////////////////
1230 ///////////////////////////////// StreamIn ///////////////////////////////////
1231 //////////////////////////////////////////////////////////////////////////////
1232
TEST_P(InputStreamTest,GetAudioSource)1233 TEST_P(InputStreamTest, GetAudioSource) {
1234 doc::test("Retrieving the audio source of an input stream should always succeed");
1235 AudioSource source;
1236 ASSERT_OK(stream->getAudioSource(returnIn(res, source)));
1237 if (res == Result::NOT_SUPPORTED) {
1238 doc::partialTest("getAudioSource is not supported");
1239 return;
1240 }
1241 ASSERT_OK(res);
1242 ASSERT_EQ(AudioSource::DEFAULT, source);
1243 }
1244
testUnitaryGain(std::function<Return<Result> (float)> setGain)1245 static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
1246 for (float value : (float[]){-INFINITY, -1.0, 1.0 + std::numeric_limits<float>::epsilon(), 2.0,
1247 INFINITY, NAN}) {
1248 EXPECT_RESULT(Result::INVALID_ARGUMENTS, setGain(value)) << "value=" << value;
1249 }
1250 // Do not consider -0.0 as an invalid value as it is == with 0.0
1251 for (float value : {-0.0, 0.0, 0.01, 0.5, 0.09, 1.0 /* Restore volume*/}) {
1252 EXPECT_OK(setGain(value)) << "value=" << value;
1253 }
1254 }
1255
testOptionalUnitaryGain(std::function<Return<Result> (float)> setGain,string debugName)1256 static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
1257 string debugName) {
1258 auto result = setGain(1);
1259 ASSERT_IS_OK(result);
1260 if (result == Result::NOT_SUPPORTED) {
1261 doc::partialTest(debugName + " is not supported");
1262 return;
1263 }
1264 testUnitaryGain(setGain);
1265 }
1266
TEST_P(InputStreamTest,SetGain)1267 TEST_P(InputStreamTest, SetGain) {
1268 doc::test("The gain of an input stream should only be set between [0,1]");
1269 testOptionalUnitaryGain([this](float volume) { return stream->setGain(volume); },
1270 "InputStream::setGain");
1271 }
1272
testPrepareForReading(IStreamIn * stream,uint32_t frameSize,uint32_t framesCount)1273 static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_t framesCount) {
1274 Result res;
1275 // Ignore output parameters as the call should fail
1276 ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
1277 [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
1278 EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
1279 }
1280
TEST_P(InputStreamTest,PrepareForReadingWithZeroBuffer)1281 TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) {
1282 doc::test("Preparing a stream for reading with a 0 sized buffer should fail");
1283 testPrepareForReading(stream.get(), 0, 0);
1284 }
1285
TEST_P(InputStreamTest,PrepareForReadingWithHugeBuffer)1286 TEST_P(InputStreamTest, PrepareForReadingWithHugeBuffer) {
1287 doc::test("Preparing a stream for reading with a 2^32 sized buffer should fail");
1288 testPrepareForReading(stream.get(), 1, std::numeric_limits<uint32_t>::max());
1289 }
1290
TEST_P(InputStreamTest,PrepareForReadingCheckOverflow)1291 TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
1292 doc::test(
1293 "Preparing a stream for reading with a overflowing sized buffer should "
1294 "fail");
1295 auto uintMax = std::numeric_limits<uint32_t>::max();
1296 testPrepareForReading(stream.get(), uintMax, uintMax);
1297 }
1298
TEST_P(InputStreamTest,GetInputFramesLost)1299 TEST_P(InputStreamTest, GetInputFramesLost) {
1300 doc::test("The number of frames lost on a never started stream should be 0");
1301 auto ret = stream->getInputFramesLost();
1302 ASSERT_IS_OK(ret);
1303 uint32_t framesLost{ret};
1304 ASSERT_EQ(0U, framesLost);
1305 }
1306
TEST_P(InputStreamTest,getCapturePosition)1307 TEST_P(InputStreamTest, getCapturePosition) {
1308 doc::test(
1309 "The capture position of a non prepared stream should not be "
1310 "retrievable or 0");
1311 uint64_t frames;
1312 uint64_t time;
1313 ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time)));
1314 ASSERT_RESULT(okOrInvalidStateOrNotSupported, res);
1315 if (res == Result::OK) {
1316 ASSERT_EQ(0U, frames);
1317 ASSERT_LE(0U, time);
1318 }
1319 }
1320
1321 //////////////////////////////////////////////////////////////////////////////
1322 ///////////////////////////////// StreamOut //////////////////////////////////
1323 //////////////////////////////////////////////////////////////////////////////
1324
TEST_P(OutputStreamTest,getLatency)1325 TEST_P(OutputStreamTest, getLatency) {
1326 doc::test("Make sure latency is over 0");
1327 auto result = stream->getLatency();
1328 ASSERT_IS_OK(result);
1329 ASSERT_GT(result, 0U);
1330 }
1331
TEST_P(OutputStreamTest,setVolume)1332 TEST_P(OutputStreamTest, setVolume) {
1333 doc::test("Try to set the output volume");
1334 testOptionalUnitaryGain([this](float volume) { return stream->setVolume(volume, volume); },
1335 "setVolume");
1336 }
1337
testPrepareForWriting(IStreamOut * stream,uint32_t frameSize,uint32_t framesCount)1338 static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32_t framesCount) {
1339 Result res;
1340 // Ignore output parameters as the call should fail
1341 ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
1342 [&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
1343 EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
1344 }
1345
TEST_P(OutputStreamTest,PrepareForWriteWithZeroBuffer)1346 TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) {
1347 doc::test("Preparing a stream for writing with a 0 sized buffer should fail");
1348 testPrepareForWriting(stream.get(), 0, 0);
1349 }
1350
TEST_P(OutputStreamTest,PrepareForWriteWithHugeBuffer)1351 TEST_P(OutputStreamTest, PrepareForWriteWithHugeBuffer) {
1352 doc::test("Preparing a stream for writing with a 2^32 sized buffer should fail");
1353 testPrepareForWriting(stream.get(), 1, std::numeric_limits<uint32_t>::max());
1354 }
1355
TEST_P(OutputStreamTest,PrepareForWritingCheckOverflow)1356 TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
1357 doc::test(
1358 "Preparing a stream for writing with a overflowing sized buffer should "
1359 "fail");
1360 auto uintMax = std::numeric_limits<uint32_t>::max();
1361 testPrepareForWriting(stream.get(), uintMax, uintMax);
1362 }
1363
1364 struct Capability {
CapabilityCapability1365 Capability(IStreamOut* stream) {
1366 EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume)));
1367 drain = extract(stream->supportsDrain());
1368 }
1369 bool pause = false;
1370 bool resume = false;
1371 bool drain = false;
1372 };
1373
TEST_P(OutputStreamTest,SupportsPauseAndResumeAndDrain)1374 TEST_P(OutputStreamTest, SupportsPauseAndResumeAndDrain) {
1375 doc::test("Implementation must expose pause, resume and drain capabilities");
1376 Capability(stream.get());
1377 }
1378
TEST_P(OutputStreamTest,GetRenderPosition)1379 TEST_P(OutputStreamTest, GetRenderPosition) {
1380 doc::test("A new stream render position should be 0 or INVALID_STATE");
1381 uint32_t dspFrames;
1382 ASSERT_OK(stream->getRenderPosition(returnIn(res, dspFrames)));
1383 if (res == Result::NOT_SUPPORTED) {
1384 doc::partialTest("getRenderPosition is not supported");
1385 return;
1386 }
1387 expectValueOrFailure(res, 0U, dspFrames, Result::INVALID_STATE);
1388 }
1389
TEST_P(OutputStreamTest,GetNextWriteTimestamp)1390 TEST_P(OutputStreamTest, GetNextWriteTimestamp) {
1391 doc::test("A new stream next write timestamp should be 0 or INVALID_STATE");
1392 uint64_t timestampUs;
1393 ASSERT_OK(stream->getNextWriteTimestamp(returnIn(res, timestampUs)));
1394 if (res == Result::NOT_SUPPORTED) {
1395 doc::partialTest("getNextWriteTimestamp is not supported");
1396 return;
1397 }
1398 expectValueOrFailure(res, uint64_t{0}, timestampUs, Result::INVALID_STATE);
1399 }
1400
1401 /** Stub implementation of out stream callback. */
1402 class MockOutCallbacks : public IStreamOutCallback {
onWriteReady()1403 Return<void> onWriteReady() override { return {}; }
onDrainReady()1404 Return<void> onDrainReady() override { return {}; }
onError()1405 Return<void> onError() override { return {}; }
1406 };
1407
isAsyncModeSupported(IStreamOut * stream)1408 static bool isAsyncModeSupported(IStreamOut* stream) {
1409 auto res = stream->setCallback(new MockOutCallbacks);
1410 stream->clearCallback(); // try to restore the no callback state, ignore
1411 // any error
1412 EXPECT_RESULT(okOrNotSupported, res);
1413 return res.isOk() ? res == Result::OK : false;
1414 }
1415
TEST_P(OutputStreamTest,SetCallback)1416 TEST_P(OutputStreamTest, SetCallback) {
1417 doc::test(
1418 "If supported, registering callback for async operation should never "
1419 "fail");
1420 if (!isAsyncModeSupported(stream.get())) {
1421 doc::partialTest("The stream does not support async operations");
1422 return;
1423 }
1424 ASSERT_OK(stream->setCallback(new MockOutCallbacks));
1425 ASSERT_OK(stream->setCallback(new MockOutCallbacks));
1426 }
1427
TEST_P(OutputStreamTest,clearCallback)1428 TEST_P(OutputStreamTest, clearCallback) {
1429 doc::test(
1430 "If supported, clearing a callback to go back to sync operation should "
1431 "not fail");
1432 if (!isAsyncModeSupported(stream.get())) {
1433 doc::partialTest("The stream does not support async operations");
1434 return;
1435 }
1436 // TODO: Clarify if clearing a non existing callback should fail
1437 ASSERT_OK(stream->setCallback(new MockOutCallbacks));
1438 ASSERT_OK(stream->clearCallback());
1439 }
1440
TEST_P(OutputStreamTest,Resume)1441 TEST_P(OutputStreamTest, Resume) {
1442 doc::test(
1443 "If supported, a stream should fail to resume if not previously "
1444 "paused");
1445 if (!Capability(stream.get()).resume) {
1446 doc::partialTest("The output stream does not support resume");
1447 return;
1448 }
1449 ASSERT_RESULT(Result::INVALID_STATE, stream->resume());
1450 }
1451
TEST_P(OutputStreamTest,Pause)1452 TEST_P(OutputStreamTest, Pause) {
1453 doc::test(
1454 "If supported, a stream should fail to pause if not previously "
1455 "started");
1456 if (!Capability(stream.get()).pause) {
1457 doc::partialTest("The output stream does not support pause");
1458 return;
1459 }
1460 ASSERT_RESULT(Result::INVALID_STATE, stream->pause());
1461 }
1462
testDrain(IStreamOut * stream,AudioDrain type)1463 static void testDrain(IStreamOut* stream, AudioDrain type) {
1464 if (!Capability(stream).drain) {
1465 doc::partialTest("The output stream does not support drain");
1466 return;
1467 }
1468 ASSERT_RESULT(Result::OK, stream->drain(type));
1469 }
1470
TEST_P(OutputStreamTest,DrainAll)1471 TEST_P(OutputStreamTest, DrainAll) {
1472 doc::test("If supported, a stream should always succeed to drain");
1473 testDrain(stream.get(), AudioDrain::ALL);
1474 }
1475
TEST_P(OutputStreamTest,DrainEarlyNotify)1476 TEST_P(OutputStreamTest, DrainEarlyNotify) {
1477 doc::test("If supported, a stream should always succeed to drain");
1478 testDrain(stream.get(), AudioDrain::EARLY_NOTIFY);
1479 }
1480
TEST_P(OutputStreamTest,FlushStop)1481 TEST_P(OutputStreamTest, FlushStop) {
1482 doc::test("If supported, a stream should always succeed to flush");
1483 auto ret = stream->flush();
1484 ASSERT_IS_OK(ret);
1485 if (ret == Result::NOT_SUPPORTED) {
1486 doc::partialTest("Flush is not supported");
1487 return;
1488 }
1489 ASSERT_OK(ret);
1490 }
1491
TEST_P(OutputStreamTest,GetPresentationPositionStop)1492 TEST_P(OutputStreamTest, GetPresentationPositionStop) {
1493 doc::test(
1494 "If supported, a stream should always succeed to retrieve the "
1495 "presentation position");
1496 uint64_t frames;
1497 TimeSpec mesureTS;
1498 ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, mesureTS)));
1499 if (res == Result::NOT_SUPPORTED) {
1500 doc::partialTest("getpresentationPosition is not supported");
1501 return;
1502 }
1503 ASSERT_EQ(0U, frames);
1504
1505 if (mesureTS.tvNSec == 0 && mesureTS.tvSec == 0) {
1506 // As the stream has never written a frame yet,
1507 // the timestamp does not really have a meaning, allow to return 0
1508 return;
1509 }
1510
1511 // Make sure the return measure is not more than 1s old.
1512 struct timespec currentTS;
1513 ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤tTS)) << errno;
1514
1515 auto toMicroSec = [](uint64_t sec, auto nsec) { return sec * 1e+6 + nsec / 1e+3; };
1516 auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec);
1517 auto mesureTime = toMicroSec(mesureTS.tvSec, mesureTS.tvNSec);
1518 ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, mesureTime);
1519 }
1520
1521 //////////////////////////////////////////////////////////////////////////////
1522 /////////////////////////////// PrimaryDevice ////////////////////////////////
1523 //////////////////////////////////////////////////////////////////////////////
1524
TEST_P(AudioPrimaryHidlTest,setVoiceVolume)1525 TEST_P(AudioPrimaryHidlTest, setVoiceVolume) {
1526 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
1527 testUnitaryGain([this](float volume) { return getDevice()->setVoiceVolume(volume); });
1528 }
1529
TEST_P(BoolAccessorPrimaryHidlTest,BtScoNrecEnabled)1530 TEST_P(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
1531 doc::test("Query and set the BT SCO NR&EC state");
1532 testAccessors<OPTIONAL>("BtScoNrecEnabled", Initial{false, OPTIONAL}, {true},
1533 &IPrimaryDevice::setBtScoNrecEnabled,
1534 &IPrimaryDevice::getBtScoNrecEnabled);
1535 }
1536
TEST_P(BoolAccessorPrimaryHidlTest,setGetBtScoWidebandEnabled)1537 TEST_P(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
1538 doc::test("Query and set the SCO whideband state");
1539 testAccessors<OPTIONAL>("BtScoWideband", Initial{false, OPTIONAL}, {true},
1540 &IPrimaryDevice::setBtScoWidebandEnabled,
1541 &IPrimaryDevice::getBtScoWidebandEnabled);
1542 }
1543
1544 using TtyModeAccessorPrimaryHidlTest =
1545 AccessorHidlTest<IPrimaryDevice::TtyMode, AudioPrimaryHidlTest>;
TEST_P(TtyModeAccessorPrimaryHidlTest,setGetTtyMode)1546 TEST_P(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
1547 doc::test("Query and set the TTY mode state");
1548 testAccessors<OPTIONAL>(
1549 "TTY mode", Initial{IPrimaryDevice::TtyMode::OFF},
1550 {IPrimaryDevice::TtyMode::HCO, IPrimaryDevice::TtyMode::VCO, IPrimaryDevice::TtyMode::FULL},
1551 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
1552 }
1553 INSTANTIATE_TEST_CASE_P(TtyModeAccessorPrimaryHidl, TtyModeAccessorPrimaryHidlTest,
1554 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1555 &DeviceParameterToString);
1556
TEST_P(BoolAccessorPrimaryHidlTest,setGetHac)1557 TEST_P(BoolAccessorPrimaryHidlTest, setGetHac) {
1558 doc::test("Query and set the HAC state");
1559 testAccessors<OPTIONAL>("HAC", Initial{false}, {true}, &IPrimaryDevice::setHacEnabled,
1560 &IPrimaryDevice::getHacEnabled);
1561 }
1562