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/expected.h>
38 #include <android-base/logging.h>
39 #include <system/audio_config.h>
40
41 // clang-format off
42 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
43 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
44 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
45 #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
46 #include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
47 #if MAJOR_VERSION >= 7
48 #include PATH(APM_XSD_ENUMS_H_FILENAME)
49 #include PATH(APM_XSD_H_FILENAME)
50 #endif
51 // clang-format on
52
53 #include <fmq/EventFlag.h>
54 #include <fmq/MessageQueue.h>
55 #include <hidl/GtestPrinter.h>
56 #include <hidl/ServiceManagement.h>
57
58 #include <common/all-versions/VersionUtils.h>
59
60 #include "utility/AssertOk.h"
61 #include "utility/Documentation.h"
62 #include "utility/ReturnIn.h"
63 #include "utility/ValidateXml.h"
64
65 #include "AudioTestDefinitions.h"
66 /** Provide version specific functions that are used in the generic tests */
67 #if MAJOR_VERSION == 2
68 #include "2.0/AudioPrimaryHidlHalUtils.h"
69 #elif MAJOR_VERSION >= 4
70 #include "4.0/AudioPrimaryHidlHalUtils.h"
71 #endif
72
73 using ::android::NO_INIT;
74 using ::android::OK;
75 using ::android::sp;
76 using ::android::status_t;
77 using ::android::hardware::EventFlag;
78 using ::android::hardware::hidl_bitfield;
79 using ::android::hardware::hidl_enum_range;
80 using ::android::hardware::hidl_handle;
81 using ::android::hardware::hidl_string;
82 using ::android::hardware::hidl_vec;
83 using ::android::hardware::IPCThreadState;
84 using ::android::hardware::kSynchronizedReadWrite;
85 using ::android::hardware::MessageQueue;
86 using ::android::hardware::MQDescriptorSync;
87 using ::android::hardware::Return;
88 using ::android::hardware::audio::common::utils::EnumBitfield;
89 using ::android::hardware::audio::common::utils::mkEnumBitfield;
90 using ::android::hardware::details::toHexString;
91
92 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
93 using namespace ::android::hardware::audio::common::test::utility;
94 using namespace ::android::hardware::audio::CPP_VERSION;
95 using ReadParameters =
96 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadParameters;
97 using ReadStatus = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadStatus;
98 using WriteCommand = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteCommand;
99 using WriteStatus = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteStatus;
100 #if MAJOR_VERSION >= 7
101 // Make an alias for enumerations generated from the APM config XSD.
102 namespace xsd {
103 using namespace ::android::audio::policy::configuration::CPP_VERSION;
104 }
105 #endif
106
107 // Typical accepted results from interface methods
108 static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
109 static auto okOrNotSupportedOrInvalidArgs = {Result::OK, Result::NOT_SUPPORTED,
110 Result::INVALID_ARGUMENTS};
111 static auto okOrInvalidState = {Result::OK, Result::INVALID_STATE};
112 static auto okOrInvalidStateOrNotSupported = {Result::OK, Result::INVALID_STATE,
113 Result::NOT_SUPPORTED};
114 static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
115 static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
116
117 #include "DeviceManager.h"
118 #if MAJOR_VERSION <= 6
119 #include "PolicyConfig.h"
120 #if MAJOR_VERSION == 6
121 #include "6.0/Generators.h"
122 #endif
123 #elif MAJOR_VERSION >= 7
124 #include "7.0/Generators.h"
125 #include "7.0/PolicyConfig.h"
126 #endif
127 #include "StreamWorker.h"
128
129 class HidlTest : public ::testing::Test {
130 public:
131 using IDevice = ::android::hardware::audio::CPP_VERSION::IDevice;
132 using IDevicesFactory = ::android::hardware::audio::CPP_VERSION::IDevicesFactory;
133
getAllFactoryInstances()134 static android::base::expected<std::vector<std::string>, std::string> getAllFactoryInstances() {
135 using ::android::hardware::audio::CPP_VERSION::IDevicesFactory;
136 const std::string factoryDescriptor = IDevicesFactory::descriptor;
137 // Make sure that the instance is the exact minor version.
138 // Using a 7.1 factory for 7.0 test is not always possible because
139 // 7.1 can be configured via the XML config to use features that are
140 // absent in 7.0.
141 auto instances = ::android::hardware::getAllHalInstanceNames(factoryDescriptor);
142 if (instances.empty()) return instances;
143 // Use the default instance for checking the implementation version.
144 auto defaultInstance = IDevicesFactory::getService("default");
145 if (defaultInstance == nullptr) {
146 return ::android::base::unexpected("Failed to obtain IDevicesFactory/default");
147 }
148 std::string actualDescriptor;
149 auto intDescRet = defaultInstance->interfaceDescriptor(
150 [&](const auto& descriptor) { actualDescriptor = descriptor; });
151 if (!intDescRet.isOk()) {
152 return ::android::base::unexpected("Failed to obtain interface descriptor: " +
153 intDescRet.description());
154 }
155 if (factoryDescriptor == actualDescriptor)
156 return instances;
157 else
158 return {};
159 }
160
161 virtual ~HidlTest() = default;
162 // public access to avoid annoyances when using this method in template classes
163 // derived from test classes
getDevice()164 sp<IDevice> getDevice() const {
165 return DeviceManager::getInstance().get(getFactoryName(), getDeviceName());
166 }
167
168 protected:
169 // Factory and device name getters to be overridden in subclasses.
170 virtual const std::string& getFactoryName() const = 0;
171 virtual const std::string& getDeviceName() const = 0;
172
getDevicesFactory()173 sp<IDevicesFactory> getDevicesFactory() const {
174 return DevicesFactoryManager::getInstance().get(getFactoryName());
175 }
resetDevice()176 bool resetDevice() const {
177 return DeviceManager::getInstance().reset(getFactoryName(), getDeviceName());
178 }
areAudioPatchesSupported()179 bool areAudioPatchesSupported() { return extract(getDevice()->supportsAudioPatches()); }
180
181 // Convenient member to store results
182 Result res;
183 };
184
185 //////////////////////////////////////////////////////////////////////////////
186 ////////////////////////// Audio policy configuration ////////////////////////
187 //////////////////////////////////////////////////////////////////////////////
188
189 // Stringify the argument.
190 #define QUOTE(x) #x
191 #define STRINGIFY(x) QUOTE(x)
192
193 static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
194
195 // Cached policy config after parsing for faster test startup
getCachedPolicyConfig()196 const PolicyConfig& getCachedPolicyConfig() {
197 static std::unique_ptr<PolicyConfig> policyConfig = [] {
198 auto config = std::make_unique<PolicyConfig>("", kConfigFileName);
199 return config;
200 }();
201 return *policyConfig;
202 }
203
TEST(CheckConfig,audioPolicyConfigurationValidation)204 TEST(CheckConfig, audioPolicyConfigurationValidation) {
205 const auto factories = HidlTest::getAllFactoryInstances();
206 if (!factories.ok()) {
207 FAIL() << factories.error();
208 }
209 if (factories.value().size() == 0) {
210 GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no factory instances "
211 "are found.";
212 }
213 RecordProperty("description",
214 "Verify that the audio policy configuration file "
215 "is valid according to the schema");
216
217 const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
218 EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
219 android::audio_get_configuration_paths(), xsd);
220 }
221
222 //////////////////////////////////////////////////////////////////////////////
223 //////////////////// Test parameter types and definitions ////////////////////
224 //////////////////////////////////////////////////////////////////////////////
225
DeviceParameterToString(const::testing::TestParamInfo<DeviceParameter> & info)226 static inline std::string DeviceParameterToString(
227 const ::testing::TestParamInfo<DeviceParameter>& info) {
228 const auto& deviceName = std::get<PARAM_DEVICE_NAME>(info.param);
229 const auto factoryName =
230 ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
231 std::get<PARAM_FACTORY_NAME>(info.param), info.index});
232 return !deviceName.empty() ? factoryName + "_" + deviceName : factoryName;
233 }
234
getDeviceParameters()235 const std::vector<DeviceParameter>& getDeviceParameters() {
236 static std::vector<DeviceParameter> parameters = [] {
237 std::vector<DeviceParameter> result;
238 const auto factories = HidlTest::getAllFactoryInstances();
239 if (!factories.ok()) return result;
240 const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
241 result.reserve(devices.size());
242 for (const auto& factoryName : factories.value()) {
243 for (const auto& deviceName : devices) {
244 if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) {
245 result.emplace_back(factoryName, deviceName);
246 }
247 }
248 }
249 return result;
250 }();
251 return parameters;
252 }
253
getDeviceParametersForFactoryTests()254 const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
255 static std::vector<DeviceParameter> parameters = [] {
256 std::vector<DeviceParameter> result;
257 const auto factories = HidlTest::getAllFactoryInstances();
258 if (!factories.ok()) return result;
259 for (const auto& factoryName : factories.value()) {
260 result.emplace_back(factoryName,
261 DeviceManager::getInstance().getPrimary(factoryName) != nullptr
262 ? DeviceManager::kPrimaryDevice
263 : "");
264 }
265 return result;
266 }();
267 return parameters;
268 }
269
getDeviceParametersForPrimaryDeviceTests()270 const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
271 static std::vector<DeviceParameter> parameters = [] {
272 std::vector<DeviceParameter> result;
273 const auto primary = std::find_if(
274 getDeviceParameters().begin(), getDeviceParameters().end(), [](const auto& elem) {
275 return std::get<PARAM_DEVICE_NAME>(elem) == DeviceManager::kPrimaryDevice;
276 });
277 if (primary != getDeviceParameters().end()) result.push_back(*primary);
278 return result;
279 }();
280 return parameters;
281 }
282
283 class AudioHidlTestWithDeviceParameter : public HidlTest,
284 public ::testing::WithParamInterface<DeviceParameter> {
285 protected:
getFactoryName()286 const std::string& getFactoryName() const override {
287 return std::get<PARAM_FACTORY_NAME>(GetParam());
288 }
getDeviceName()289 const std::string& getDeviceName() const override {
290 return std::get<PARAM_DEVICE_NAME>(GetParam());
291 }
292 };
293
294 class AudioPolicyConfigTest : public AudioHidlTestWithDeviceParameter {
295 public:
SetUp()296 void SetUp() override {
297 ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base
298 auto& policyConfig = getCachedPolicyConfig();
299 ASSERT_EQ(0, policyConfig.getStatus()) << policyConfig.getError();
300 }
301 };
302
TEST_P(AudioPolicyConfigTest,LoadAudioPolicyXMLConfiguration)303 TEST_P(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) {
304 doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)");
305 }
306
TEST_P(AudioPolicyConfigTest,HasPrimaryModule)307 TEST_P(AudioPolicyConfigTest, HasPrimaryModule) {
308 auto& policyConfig = getCachedPolicyConfig();
309 ASSERT_TRUE(policyConfig.getPrimaryModule() != nullptr)
310 << "Could not find primary module in configuration file: "
311 << policyConfig.getFilePath();
312 }
313
314 INSTANTIATE_TEST_CASE_P(AudioHidl, AudioPolicyConfigTest,
315 ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
316 &DeviceParameterToString);
317 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
318 // list is empty, this isn't a problem.
319 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPolicyConfigTest);
320
321 //////////////////////////////////////////////////////////////////////////////
322 ////////////////////// getService audio_devices_factory //////////////////////
323 //////////////////////////////////////////////////////////////////////////////
324
325 // Test audio devices factory
326 class AudioHidlTest : public AudioHidlTestWithDeviceParameter {
327 public:
328 using IPrimaryDevice = ::android::hardware::audio::CPP_VERSION::IPrimaryDevice;
329
SetUp()330 void SetUp() override {
331 ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base
332 ASSERT_TRUE(getDevicesFactory() != nullptr);
333 }
334 };
335
TEST_P(AudioHidlTest,GetAudioDevicesFactoryService)336 TEST_P(AudioHidlTest, GetAudioDevicesFactoryService) {
337 doc::test("Test the getService");
338 }
339
TEST_P(AudioHidlTest,OpenDeviceInvalidParameter)340 TEST_P(AudioHidlTest, OpenDeviceInvalidParameter) {
341 doc::test("Test passing an invalid parameter to openDevice");
342 Result result;
343 sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IDevice> device;
344 #if MAJOR_VERSION == 2
345 auto invalidDevice = IDevicesFactory::Device(-1);
346 #elif MAJOR_VERSION >= 4
347 auto invalidDevice = "Non existing device";
348 #endif
349 ASSERT_OK(getDevicesFactory()->openDevice(invalidDevice, returnIn(result, device)));
350 ASSERT_EQ(Result::INVALID_ARGUMENTS, result);
351 ASSERT_TRUE(device == nullptr);
352 }
353
354 INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest,
355 ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
356 &DeviceParameterToString);
357 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
358 // list is empty, this isn't a problem.
359 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioHidlTest);
360
361 //////////////////////////////////////////////////////////////////////////////
362 /////////////////////////////// openDevice ///////////////////////////////////
363 //////////////////////////////////////////////////////////////////////////////
364
365 // Test all audio devices
366 class AudioHidlDeviceTest : public AudioHidlTest {
367 public:
SetUp()368 void SetUp() override {
369 ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base
370 ASSERT_TRUE(getDevice() != nullptr);
371 }
372 };
373
TEST_P(AudioHidlDeviceTest,OpenDevice)374 TEST_P(AudioHidlDeviceTest, OpenDevice) {
375 doc::test("Test openDevice (called during setup)");
376 }
377
TEST_P(AudioHidlDeviceTest,Init)378 TEST_P(AudioHidlDeviceTest, Init) {
379 doc::test("Test that the audio hal initialized correctly");
380 ASSERT_OK(getDevice()->initCheck());
381 }
382
383 INSTANTIATE_TEST_CASE_P(AudioHidlDevice, AudioHidlDeviceTest,
384 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
385 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
386 // list is empty, this isn't a problem.
387 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioHidlDeviceTest);
388
389 //////////////////////////////////////////////////////////////////////////////
390 /////////////////////////////// openDevice primary ///////////////////////////
391 //////////////////////////////////////////////////////////////////////////////
392
393 // Test the primary device
394 class AudioPrimaryHidlTest : public AudioHidlDeviceTest {
395 public:
SetUp()396 void SetUp() override {
397 ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp()); // setup base
398 ASSERT_TRUE(getDevice() != nullptr);
399 }
400
401 // public access to avoid annoyances when using this method in template classes
402 // derived from test classes
getDevice()403 sp<IPrimaryDevice> getDevice() const {
404 return DeviceManager::getInstance().getPrimary(getFactoryName());
405 }
406 };
407
TEST_P(AudioPrimaryHidlTest,OpenPrimaryDevice)408 TEST_P(AudioPrimaryHidlTest, OpenPrimaryDevice) {
409 doc::test("Test openPrimaryDevice (called during setup)");
410 }
411
412 INSTANTIATE_TEST_CASE_P(AudioPrimaryHidl, AudioPrimaryHidlTest,
413 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
414 &DeviceParameterToString);
415 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
416 // list is empty, this isn't a problem.
417 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPrimaryHidlTest);
418
419 //////////////////////////////////////////////////////////////////////////////
420 ///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
421 //////////////////////////////////////////////////////////////////////////////
422
423 template <class Property, class BaseTestClass = AudioHidlDeviceTest>
424 class AccessorHidlTest : public BaseTestClass {
425 protected:
426 enum Optionality { REQUIRED, OPTIONAL };
427 struct Initial { // Initial property value
valueInitial428 Initial(Property value, Optionality check = REQUIRED) : value(value), check(check) {}
429 Property value;
430 Optionality check; // If this initial value should be checked
431 };
432 using BaseTestClass::res;
433 /** Test a property getter and setter.
434 * The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
435 */
436 template <Optionality optionality = REQUIRED, class IUTGetter, class Getter, class Setter>
437 void testAccessors(IUTGetter iutGetter, const std::string& propertyName,
438 const Initial expectedInitial, std::list<Property> valuesToTest,
439 Setter setter, Getter getter,
440 const std::vector<Property>& invalidValues = {}) {
441 const auto expectedResults = {Result::OK,
442 optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
443
444 Property initialValue = expectedInitial.value;
445 ASSERT_OK(((this->*iutGetter)().get()->*getter)(returnIn(res, initialValue)));
446 ASSERT_RESULT(expectedResults, res);
447 if (res == Result::OK && expectedInitial.check == REQUIRED) {
448 EXPECT_EQ(expectedInitial.value, initialValue);
449 }
450
451 valuesToTest.push_front(expectedInitial.value);
452 valuesToTest.push_back(initialValue);
453 for (Property setValue : valuesToTest) {
454 SCOPED_TRACE("Test " + propertyName + " getter and setter for " +
455 testing::PrintToString(setValue));
456 auto ret = ((this->*iutGetter)().get()->*setter)(setValue);
457 ASSERT_RESULT(expectedResults, ret);
458 if (ret == Result::NOT_SUPPORTED) {
459 doc::partialTest(propertyName + " setter is not supported");
460 break;
461 }
462 Property getValue;
463 // Make sure the getter returns the same value just set
464 ASSERT_OK(((this->*iutGetter)().get()->*getter)(returnIn(res, getValue)));
465 ASSERT_RESULT(expectedResults, res);
466 if (res == Result::NOT_SUPPORTED) {
467 doc::partialTest(propertyName + " getter is not supported");
468 continue;
469 }
470 EXPECT_EQ(setValue, getValue);
471 }
472
473 for (Property invalidValue : invalidValues) {
474 SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
475 testing::PrintToString(invalidValue));
476 EXPECT_RESULT(invalidArgsOrNotSupported,
477 ((this->*iutGetter)().get()->*setter)(invalidValue));
478 }
479
480 // Restore initial value
481 EXPECT_RESULT(expectedResults, ((this->*iutGetter)().get()->*setter)(initialValue));
482 }
483 template <Optionality optionality = REQUIRED, class Getter, class Setter>
484 void testAccessors(const std::string& propertyName, const Initial expectedInitial,
485 std::list<Property> valuesToTest, Setter setter, Getter getter,
486 const std::vector<Property>& invalidValues = {}) {
487 testAccessors<optionality>(&BaseTestClass::getDevice, propertyName, expectedInitial,
488 valuesToTest, setter, getter, invalidValues);
489 }
490 };
491
492 using BoolAccessorHidlTest = AccessorHidlTest<bool>;
493 using BoolAccessorPrimaryHidlTest = AccessorHidlTest<bool, AudioPrimaryHidlTest>;
494
TEST_P(BoolAccessorHidlTest,MicMuteTest)495 TEST_P(BoolAccessorHidlTest, MicMuteTest) {
496 doc::test("Check that the mic can be muted and unmuted");
497 testAccessors<OPTIONAL>("mic mute", Initial{false}, {true}, &IDevice::setMicMute,
498 &IDevice::getMicMute);
499 // TODO: check that the mic is really muted (all sample are 0)
500 }
501
TEST_P(BoolAccessorHidlTest,MasterMuteTest)502 TEST_P(BoolAccessorHidlTest, MasterMuteTest) {
503 doc::test("If master mute is supported, try to mute and unmute the master output");
504 testAccessors<OPTIONAL>("master mute", Initial{false}, {true}, &IDevice::setMasterMute,
505 &IDevice::getMasterMute);
506 // TODO: check that the master volume is really muted
507 }
508
509 INSTANTIATE_TEST_CASE_P(BoolAccessorHidl, BoolAccessorHidlTest,
510 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
511 INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest,
512 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
513 &DeviceParameterToString);
514 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
515 // list is empty, this isn't a problem.
516 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BoolAccessorHidlTest);
517 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BoolAccessorPrimaryHidlTest);
518
519 using FloatAccessorHidlTest = AccessorHidlTest<float>;
TEST_P(FloatAccessorHidlTest,MasterVolumeTest)520 TEST_P(FloatAccessorHidlTest, MasterVolumeTest) {
521 doc::test("Test the master volume if supported");
522 testAccessors<OPTIONAL>(
523 "master volume", Initial{1}, {0, 0.5}, &IDevice::setMasterVolume, &IDevice::getMasterVolume,
524 {-0.1, 1.1, NAN, INFINITY, -INFINITY, 1 + std::numeric_limits<float>::epsilon()});
525 // TODO: check that the master volume is really changed
526 }
527
528 INSTANTIATE_TEST_CASE_P(FloatAccessorHidl, FloatAccessorHidlTest,
529 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
530 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
531 // list is empty, this isn't a problem.
532 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FloatAccessorHidlTest);
533
534 //////////////////////////////////////////////////////////////////////////////
535 //////////////////////////////// AudioPatches ////////////////////////////////
536 //////////////////////////////////////////////////////////////////////////////
537
538 class AudioPatchHidlTest : public AudioHidlDeviceTest {
539 public:
SetUp()540 void SetUp() override {
541 ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp()); // setup base
542 if (!areAudioPatchesSupported()) {
543 GTEST_SKIP() << "Audio patches are not supported";
544 }
545 }
546 };
547
TEST_P(AudioPatchHidlTest,AudioPatches)548 TEST_P(AudioPatchHidlTest, AudioPatches) {
549 doc::test("Test if audio patches are supported");
550 // TODO: test audio patches
551 }
552
553 INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest,
554 ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
555 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
556 // list is empty, this isn't a problem.
557 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPatchHidlTest);
558
559 #if MAJOR_VERSION >= 4
SanitizeStringForGTestName(const std::string & s)560 static std::string SanitizeStringForGTestName(const std::string& s) {
561 std::string result = s;
562 for (size_t i = 0; i < result.size(); i++) {
563 // gtest test names must only contain alphanumeric characters
564 if (!std::isalnum(result[i])) result[i] = '_';
565 }
566 return result;
567 }
568 #endif
569
570 /** Generate a test name based on an audio config.
571 *
572 * As the only parameter changing are channel mask and sample rate,
573 * only print those ones in the test name.
574 */
DeviceConfigParameterToString(const testing::TestParamInfo<DeviceConfigParameter> & info)575 static std::string DeviceConfigParameterToString(
576 const testing::TestParamInfo<DeviceConfigParameter>& info) {
577 const AudioConfig& config = std::get<PARAM_CONFIG>(info.param);
578 const auto deviceName = DeviceParameterToString(::testing::TestParamInfo<DeviceParameter>{
579 std::get<PARAM_DEVICE>(info.param), info.index});
580 const auto devicePart =
581 (deviceName.empty() ? "" : deviceName + "_") + std::to_string(info.index);
582 // The types had changed a lot between versions 2, 4..6 and 7. Use separate
583 // code sections for easier understanding.
584 #if MAJOR_VERSION == 2
585 const auto configPart =
586 std::to_string(config.sampleRateHz) + "_" +
587 // "MONO" is more clear than "FRONT_LEFT"
588 (config.channelMask == AudioChannelMask::OUT_MONO ||
589 config.channelMask == AudioChannelMask::IN_MONO
590 ? "MONO"
591 : ::testing::PrintToString(config.channelMask)) +
592 "_" +
593 std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
594 std::get<PARAM_FLAGS>(info.param));
595 #elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
596 const auto configPart =
597 std::to_string(config.sampleRateHz) + "_" +
598 // "MONO" is more clear than "FRONT_LEFT"
599 (config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
600 config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO)
601 ? "MONO"
602 // In V4 and above the channel mask is a bitfield.
603 // Printing its value using HIDL's toString for a bitfield emits a lot of extra
604 // text due to overlapping constant values. Instead, we print the bitfield
605 // value as if it was a single value + its hex representation
606 : SanitizeStringForGTestName(
607 ::testing::PrintToString(AudioChannelMask(config.channelMask)) +
608 "_" + toHexString(config.channelMask))) +
609 "_" +
610 SanitizeStringForGTestName(std::visit(
611 [](auto&& arg) -> std::string {
612 using T = std::decay_t<decltype(arg)>;
613 // Need to use FQN of toString to avoid confusing the compiler
614 return ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::
615 toString<T>(hidl_bitfield<T>(arg));
616 },
617 std::get<PARAM_FLAGS>(info.param)));
618 #elif MAJOR_VERSION >= 7
619 const auto configPart =
620 ::testing::PrintToString(std::get<PARAM_ATTACHED_DEV_ADDR>(info.param).deviceType) +
621 "_" + std::to_string(config.base.sampleRateHz) + "_" +
622 // The channel masks and flags are vectors of strings, just need to sanitize them.
623 SanitizeStringForGTestName(::testing::PrintToString(config.base.channelMask)) + "_" +
624 SanitizeStringForGTestName(::testing::PrintToString(std::get<PARAM_FLAGS>(info.param)));
625 #endif
626 return devicePart + "__" + configPart;
627 }
628
629 class AudioHidlTestWithDeviceConfigParameter
630 : public HidlTest,
631 public ::testing::WithParamInterface<DeviceConfigParameter> {
632 protected:
SetUp()633 void SetUp() override {
634 ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base
635 ASSERT_TRUE(getDevicesFactory() != nullptr);
636 ASSERT_TRUE(getDevice() != nullptr);
637 }
getFactoryName()638 const std::string& getFactoryName() const override {
639 return std::get<PARAM_FACTORY_NAME>(std::get<PARAM_DEVICE>(GetParam()));
640 }
getDeviceName()641 const std::string& getDeviceName() const override {
642 return std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(GetParam()));
643 }
getConfig()644 const AudioConfig& getConfig() const { return std::get<PARAM_CONFIG>(GetParam()); }
645 #if MAJOR_VERSION == 2
getInputFlags()646 AudioInputFlag getInputFlags() const {
647 return std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam()));
648 }
getOutputFlags()649 AudioOutputFlag getOutputFlags() const {
650 return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
651 }
652 #elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
getInputFlags()653 hidl_bitfield<AudioInputFlag> getInputFlags() const {
654 return hidl_bitfield<AudioInputFlag>(
655 std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
656 }
getOutputFlags()657 hidl_bitfield<AudioOutputFlag> getOutputFlags() const {
658 return hidl_bitfield<AudioOutputFlag>(
659 std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
660 }
661 #elif MAJOR_VERSION >= 7
getAttachedDeviceAddress()662 DeviceAddress getAttachedDeviceAddress() const {
663 return std::get<PARAM_ATTACHED_DEV_ADDR>(GetParam());
664 }
getInputFlags()665 hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
getOutputFlags()666 hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
667 #endif
668 };
669
670 #if MAJOR_VERSION <= 6
671 #define AUDIO_PRIMARY_HIDL_HAL_TEST
672 #include "ConfigHelper.h"
673 #undef AUDIO_PRIMARY_HIDL_HAL_TEST
674 #endif
675
676 //////////////////////////////////////////////////////////////////////////////
677 ///////////////////////////// getInputBufferSize /////////////////////////////
678 //////////////////////////////////////////////////////////////////////////////
679
680 // FIXME: execute input test only if platform declares
681 // android.hardware.microphone
682 // how to get this value ? is it a property ???
683
684 class AudioCaptureConfigTest : public AudioHidlTestWithDeviceConfigParameter {
685 protected:
inputBufferSizeTest(const AudioConfig & audioConfig,bool supportRequired)686 void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
687 uint64_t bufferSize;
688 ASSERT_OK(getDevice()->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
689
690 switch (res) {
691 case Result::INVALID_ARGUMENTS:
692 EXPECT_FALSE(supportRequired);
693 break;
694 case Result::OK:
695 // Check that the buffer is of a sane size
696 // For now only that it is > 0
697 EXPECT_GT(bufferSize, uint64_t(0));
698 break;
699 default:
700 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
701 }
702 }
703 };
704
705 // Test that the required capture config and those declared in the policy are
706 // indeed supported
707 class RequiredInputBufferSizeTest : public AudioCaptureConfigTest {};
TEST_P(RequiredInputBufferSizeTest,RequiredInputBufferSizeTest)708 TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
709 doc::test(
710 "Input buffer size must be retrievable for a format with required "
711 "support.");
712 inputBufferSizeTest(getConfig(), true);
713 }
714
715 // Test that the recommended capture config are supported or lead to a
716 // INVALID_ARGUMENTS return
717 class OptionalInputBufferSizeTest : public AudioCaptureConfigTest {};
TEST_P(OptionalInputBufferSizeTest,OptionalInputBufferSizeTest)718 TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
719 doc::test(
720 "Input buffer size should be retrievable for a format with recommended "
721 "support.");
722 inputBufferSizeTest(getConfig(), false);
723 }
724
725 #if MAJOR_VERSION <= 5
726 // For V2..5 test the primary device according to CDD requirements.
727 INSTANTIATE_TEST_CASE_P(
728 RequiredInputBufferSize, RequiredInputBufferSizeTest,
729 ::testing::Combine(
730 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
731 ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()),
732 ::testing::Values(AudioInputFlag::NONE)),
733 &DeviceConfigParameterToString);
734 INSTANTIATE_TEST_CASE_P(
735 RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
736 ::testing::Combine(
737 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
738 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
739 ::testing::Values(AudioInputFlag::NONE)),
740 &DeviceConfigParameterToString);
741 #elif MAJOR_VERSION >= 6
742 INSTANTIATE_TEST_CASE_P(SupportedInputBufferSize, RequiredInputBufferSizeTest,
743 ::testing::ValuesIn(getInputDeviceConfigParameters()),
744 &DeviceConfigParameterToString);
745 #endif
746 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
747 // list is empty, this isn't a problem.
748 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OptionalInputBufferSizeTest);
749 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RequiredInputBufferSizeTest);
750
751 //////////////////////////////////////////////////////////////////////////////
752 /////////////////////////////// setScreenState ///////////////////////////////
753 //////////////////////////////////////////////////////////////////////////////
754
TEST_P(AudioHidlDeviceTest,setScreenState)755 TEST_P(AudioHidlDeviceTest, setScreenState) {
756 doc::test("Check that the hal can receive the screen state");
757 for (bool turnedOn : {false, true, true, false, false}) {
758 ASSERT_RESULT(okOrNotSupported, getDevice()->setScreenState(turnedOn));
759 }
760 }
761
762 //////////////////////////////////////////////////////////////////////////////
763 //////////////////////////// {get,set}Parameters /////////////////////////////
764 //////////////////////////////////////////////////////////////////////////////
765
TEST_P(AudioHidlDeviceTest,getParameters)766 TEST_P(AudioHidlDeviceTest, getParameters) {
767 doc::test("Check that the hal can set and get parameters");
768 hidl_vec<ParameterValue> context;
769 hidl_vec<hidl_string> keys;
770 hidl_vec<ParameterValue> values;
771 ASSERT_OK(Parameters::get(getDevice(), keys, returnIn(res, values)));
772 ASSERT_RESULT(okOrNotSupported, res);
773 ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values));
774 values.resize(0);
775 ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values));
776 }
777
778 //////////////////////////////////////////////////////////////////////////////
779 //////////////////////////////// debugDebug //////////////////////////////////
780 //////////////////////////////////////////////////////////////////////////////
781
782 template <class DebugDump>
testDebugDump(DebugDump debugDump)783 static void testDebugDump(DebugDump debugDump) {
784 // File descriptors to our pipe. fds[0] corresponds to the read end and
785 // fds[1] to the write end.
786 int fds[2];
787 ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
788
789 // Make sure that the pipe is at least 1 MB in size. The test process runs
790 // in su domain, so it should be safe to make this call.
791 fcntl(fds[0], F_SETPIPE_SZ, 1 << 20);
792
793 // Wrap the temporary file file descriptor in a native handle
794 auto* nativeHandle = native_handle_create(1, 0);
795 ASSERT_NE(nullptr, nativeHandle);
796 nativeHandle->data[0] = fds[1];
797
798 // Wrap this native handle in a hidl handle
799 hidl_handle handle;
800 handle.setTo(nativeHandle, false /*take ownership*/);
801
802 ASSERT_OK(debugDump(handle));
803
804 // Check that at least one bit was written by the hal
805 // TODO: debugDump does not return a Result.
806 // This mean that the hal can not report that it not implementing the
807 // function.
808 char buff;
809 if (read(fds[0], &buff, 1) != 1) {
810 doc::note("debugDump does not seem implemented");
811 }
812 EXPECT_EQ(0, close(fds[0])) << errno;
813 EXPECT_EQ(0, close(fds[1])) << errno;
814 }
815
TEST_P(AudioHidlDeviceTest,DebugDump)816 TEST_P(AudioHidlDeviceTest, DebugDump) {
817 doc::test("Check that the hal can dump its state without error");
818 testDebugDump([this](const auto& handle) { return dump(getDevice(), handle); });
819 }
820
TEST_P(AudioHidlDeviceTest,DebugDumpInvalidArguments)821 TEST_P(AudioHidlDeviceTest, DebugDumpInvalidArguments) {
822 doc::test("Check that the hal dump doesn't crash on invalid arguments");
823 ASSERT_OK(dump(getDevice(), hidl_handle()));
824 }
825
826 //////////////////////////////////////////////////////////////////////////////
827 ////////////////////////// open{Output,Input}Stream //////////////////////////
828 //////////////////////////////////////////////////////////////////////////////
829
getNextIoHandle()830 static inline AudioIoHandle getNextIoHandle() {
831 static AudioIoHandle lastHandle{};
832 return ++lastHandle;
833 }
834
835 // This class is also used by some device tests.
836 template <class Stream>
837 class StreamHelper {
838 public:
839 // StreamHelper doesn't own the stream, this is for simpler stream lifetime management.
StreamHelper(sp<Stream> & stream)840 explicit StreamHelper(sp<Stream>& stream) : mStream(stream) {}
841 template <class Open>
open(Open openStream,const AudioConfig & config,Result * res,AudioConfig * suggestedConfigPtr)842 void open(Open openStream, const AudioConfig& config, Result* res,
843 AudioConfig* suggestedConfigPtr) {
844 AudioConfig suggestedConfig{};
845 bool retryWithSuggestedConfig = true;
846 if (suggestedConfigPtr == nullptr) {
847 suggestedConfigPtr = &suggestedConfig;
848 retryWithSuggestedConfig = false;
849 }
850 ASSERT_OK(openStream(mIoHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
851 switch (*res) {
852 case Result::OK:
853 ASSERT_TRUE(mStream != nullptr);
854 *suggestedConfigPtr = config;
855 break;
856 case Result::INVALID_ARGUMENTS:
857 ASSERT_TRUE(mStream == nullptr);
858 if (retryWithSuggestedConfig) {
859 AudioConfig suggestedConfigRetry;
860 ASSERT_OK(openStream(mIoHandle, *suggestedConfigPtr,
861 returnIn(*res, mStream, suggestedConfigRetry)));
862 ASSERT_OK(*res);
863 ASSERT_TRUE(mStream != nullptr);
864 }
865 break;
866 default:
867 FAIL() << "Invalid return status: " << ::testing::PrintToString(*res);
868 }
869 }
close(bool clear,Result * res)870 void close(bool clear, Result* res) {
871 auto ret = mStream->close();
872 EXPECT_TRUE(ret.isOk());
873 *res = ret;
874 if (clear) {
875 mStream.clear();
876 #if MAJOR_VERSION <= 5
877 // FIXME: there is no way to know when the remote IStream is being destroyed
878 // Binder does not support testing if an object is alive, thus
879 // wait for 100ms to let the binder destruction propagates and
880 // the remote device has the time to be destroyed.
881 // flushCommand makes sure all local command are sent, thus should reduce
882 // the latency between local and remote destruction.
883 IPCThreadState::self()->flushCommands();
884 usleep(100 * 1000);
885 #endif
886 }
887 }
getIoHandle()888 AudioIoHandle getIoHandle() const { return mIoHandle; }
889
890 private:
891 const AudioIoHandle mIoHandle = getNextIoHandle();
892 sp<Stream>& mStream;
893 };
894
895 template <class Stream>
896 class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
897 public:
898 // public access to avoid annoyances when using this method in template classes
899 // derived from test classes
getStream()900 sp<Stream> getStream() const { return stream; }
901
902 protected:
OpenStreamTest()903 OpenStreamTest() : AudioHidlTestWithDeviceConfigParameter(), helper(stream) {}
904 template <class Open>
testOpen(Open openStream,const AudioConfig & config)905 void testOpen(Open openStream, const AudioConfig& config) {
906 // TODO: only allow failure for RecommendedPlaybackAudioConfig
907 ASSERT_NO_FATAL_FAILURE(helper.open(openStream, config, &res, &audioConfig));
908 open = true;
909 }
910
911 Result closeStream(bool clear = true) {
912 open = false;
913 helper.close(clear, &res);
914 return res;
915 }
916
TearDown()917 void TearDown() override {
918 if (open) {
919 ASSERT_OK(closeStream());
920 }
921 AudioHidlTestWithDeviceConfigParameter::TearDown();
922 }
923
924 protected:
925 AudioConfig audioConfig;
926 DeviceAddress address = {};
927 sp<Stream> stream;
928 StreamHelper<Stream> helper;
929 bool open = false;
930 };
931
932 ////////////////////////////// openOutputStream //////////////////////////////
933
934 class StreamWriter : public StreamWorker<StreamWriter> {
935 public:
936 using IStreamOut = ::android::hardware::audio::CPP_VERSION::IStreamOut;
937
StreamWriter(IStreamOut * stream,size_t bufferSize)938 StreamWriter(IStreamOut* stream, size_t bufferSize)
939 : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
StreamWriter(IStreamOut * stream,size_t bufferSize,std::vector<uint8_t> && data,std::function<void ()> onDataStart,std::function<bool ()> onDataWrap)940 StreamWriter(IStreamOut* stream, size_t bufferSize, std::vector<uint8_t>&& data,
941 std::function<void()> onDataStart, std::function<bool()> onDataWrap)
942 : mStream(stream),
943 mBufferSize(bufferSize),
944 mData(std::move(data)),
945 mOnDataStart(onDataStart),
946 mOnDataWrap(onDataWrap) {
947 ALOGI("StreamWriter data size: %d", (int)mData.size());
948 }
~StreamWriter()949 ~StreamWriter() {
950 stop();
951 if (mEfGroup) {
952 EventFlag::deleteEventFlag(&mEfGroup);
953 }
954 }
955
956 typedef MessageQueue<WriteCommand, ::android::hardware::kSynchronizedReadWrite> CommandMQ;
957 typedef MessageQueue<uint8_t, ::android::hardware::kSynchronizedReadWrite> DataMQ;
958 typedef MessageQueue<WriteStatus, ::android::hardware::kSynchronizedReadWrite> StatusMQ;
959
workerInit()960 bool workerInit() {
961 std::unique_ptr<CommandMQ> tempCommandMQ;
962 std::unique_ptr<DataMQ> tempDataMQ;
963 std::unique_ptr<StatusMQ> tempStatusMQ;
964 Result retval;
965 Return<void> ret = mStream->prepareForWriting(
966 1, mBufferSize,
967 [&](Result r, const CommandMQ::Descriptor& commandMQ,
968 const DataMQ::Descriptor& dataMQ, const StatusMQ::Descriptor& statusMQ,
969 const auto& /*halThreadInfo*/) {
970 retval = r;
971 if (retval == Result::OK) {
972 tempCommandMQ.reset(new CommandMQ(commandMQ));
973 tempDataMQ.reset(new DataMQ(dataMQ));
974 tempStatusMQ.reset(new StatusMQ(statusMQ));
975 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
976 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
977 }
978 }
979 });
980 if (!ret.isOk()) {
981 ALOGE("Transport error while calling prepareForWriting: %s", ret.description().c_str());
982 return false;
983 }
984 if (retval != Result::OK) {
985 ALOGE("Error from prepareForWriting: %d", retval);
986 return false;
987 }
988 if (!tempCommandMQ || !tempCommandMQ->isValid() || !tempDataMQ || !tempDataMQ->isValid() ||
989 !tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
990 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
991 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
992 "Command message queue for writing is invalid");
993 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
994 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(),
995 "Data message queue for writing is invalid");
996 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
997 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
998 "Status message queue for writing is invalid");
999 ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
1000 return false;
1001 }
1002 mCommandMQ = std::move(tempCommandMQ);
1003 mDataMQ = std::move(tempDataMQ);
1004 mStatusMQ = std::move(tempStatusMQ);
1005 return true;
1006 }
1007
workerCycle()1008 bool workerCycle() {
1009 WriteCommand cmd = WriteCommand::WRITE;
1010 if (!mCommandMQ->write(&cmd)) {
1011 ALOGE("command message queue write failed");
1012 return false;
1013 }
1014 if (mDataPosition == 0) mOnDataStart();
1015 const size_t dataSize = std::min(mData.size() - mDataPosition, mDataMQ->availableToWrite());
1016 bool success = mDataMQ->write(mData.data() + mDataPosition, dataSize);
1017 bool wrapped = false;
1018 ALOGE_IF(!success, "data message queue write failed");
1019 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
1020
1021 uint32_t efState = 0;
1022 retry:
1023 status_t ret =
1024 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
1025 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
1026 WriteStatus writeStatus;
1027 writeStatus.retval = Result::NOT_INITIALIZED;
1028 if (!mStatusMQ->read(&writeStatus)) {
1029 ALOGE("status message read failed");
1030 success = false;
1031 }
1032 if (writeStatus.retval != Result::OK) {
1033 ALOGE("bad write status: %d", writeStatus.retval);
1034 success = false;
1035 }
1036 mDataPosition += writeStatus.reply.written;
1037 if (mDataPosition >= mData.size()) {
1038 mDataPosition = 0;
1039 wrapped = true;
1040 }
1041 }
1042 if (ret == -EAGAIN || ret == -EINTR) {
1043 // Spurious wakeup. This normally retries no more than once.
1044 goto retry;
1045 } else if (ret) {
1046 ALOGE("bad wait status: %d", ret);
1047 success = false;
1048 }
1049 if (wrapped) {
1050 success = mOnDataWrap();
1051 }
1052 return success;
1053 }
1054
1055 private:
1056 IStreamOut* const mStream;
1057 const size_t mBufferSize;
1058 std::vector<uint8_t> mData;
1059 std::function<void()> mOnDataStart = []() {};
1060 std::function<bool()> mOnDataWrap = []() { return true; };
1061 size_t mDataPosition = 0;
1062 std::unique_ptr<CommandMQ> mCommandMQ;
1063 std::unique_ptr<DataMQ> mDataMQ;
1064 std::unique_ptr<StatusMQ> mStatusMQ;
1065 EventFlag* mEfGroup = nullptr;
1066 };
1067
1068 class OutputStreamTest
1069 : public OpenStreamTest<::android::hardware::audio::CPP_VERSION::IStreamOut> {
1070 protected:
SetUp()1071 void SetUp() override {
1072 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
1073 #if MAJOR_VERSION <= 6
1074 address.device = AudioDevice::OUT_DEFAULT;
1075 #elif MAJOR_VERSION >= 7
1076 address = getAttachedDeviceAddress();
1077 #endif
1078 const AudioConfig& config = getConfig();
1079 auto flags = getOutputFlags();
1080 testOpen(
1081 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
1082 #if MAJOR_VERSION == 2
1083 return getDevice()->openOutputStream(handle, address, config, flags, cb);
1084 #elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0))
1085 return getDevice()->openOutputStream(handle, address, config, flags,
1086 initMetadata, cb);
1087 #elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
1088 return getDevice()->openOutputStream_7_1(handle, address, config, flags,
1089 initMetadata, cb);
1090 #endif
1091 },
1092 config);
1093 }
1094 #if MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
1095
1096 const SourceMetadata initMetadata = {
1097 { { AudioUsage::MEDIA,
1098 AudioContentType::MUSIC,
1099 1 /* gain */ } }};
1100 #elif MAJOR_VERSION >= 7
1101 protected:
1102 const SourceMetadata initMetadata = {
1103 { { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
1104 toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
1105 1 /* gain */,
1106 toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
1107 {} } }};
1108 #endif
1109 };
TEST_P(OutputStreamTest,OpenOutputStreamTest)1110 TEST_P(OutputStreamTest, OpenOutputStreamTest) {
1111 doc::test(
1112 "Check that output streams can be open with the required and "
1113 "recommended config");
1114 // Open done in SetUp
1115 }
1116
1117 #if MAJOR_VERSION <= 5
1118 // For V2..5 test the primary device according to CDD requirements.
1119 INSTANTIATE_TEST_CASE_P(
1120 RequiredOutputStreamConfigSupport, OutputStreamTest,
1121 ::testing::Combine(
1122 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1123 ::testing::ValuesIn(ConfigHelper::getRequiredSupportPlaybackAudioConfig()),
1124 ::testing::Values(AudioOutputFlag::NONE)),
1125 &DeviceConfigParameterToString);
1126 INSTANTIATE_TEST_CASE_P(
1127 RecommendedOutputStreamConfigSupport, OutputStreamTest,
1128 ::testing::Combine(
1129 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1130 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportPlaybackAudioConfig()),
1131 ::testing::Values(AudioOutputFlag::NONE)),
1132 &DeviceConfigParameterToString);
1133 #elif MAJOR_VERSION >= 6
1134 // For V6 and above test according to the audio policy manager configuration.
1135 // This is more correct as CDD is written from the apps perspective.
1136 // Audio system provides necessary format conversions for missing configurations.
1137 INSTANTIATE_TEST_CASE_P(DeclaredOutputStreamConfigSupport, OutputStreamTest,
1138 ::testing::ValuesIn(getOutputDeviceConfigParameters()),
1139 &DeviceConfigParameterToString);
1140 #endif
1141 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
1142 // list is empty, this isn't a problem.
1143 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamTest);
1144
1145 ////////////////////////////// openInputStream //////////////////////////////
1146
1147 class StreamReader : public StreamWorker<StreamReader> {
1148 public:
1149 using IStreamIn = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn;
1150
StreamReader(IStreamIn * stream,size_t bufferSize)1151 StreamReader(IStreamIn* stream, size_t bufferSize)
1152 : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
~StreamReader()1153 ~StreamReader() {
1154 stop();
1155 if (mEfGroup) {
1156 EventFlag::deleteEventFlag(&mEfGroup);
1157 }
1158 }
1159
1160 typedef MessageQueue<ReadParameters, ::android::hardware::kSynchronizedReadWrite> CommandMQ;
1161 typedef MessageQueue<uint8_t, ::android::hardware::kSynchronizedReadWrite> DataMQ;
1162 typedef MessageQueue<ReadStatus, ::android::hardware::kSynchronizedReadWrite> StatusMQ;
1163
workerInit()1164 bool workerInit() {
1165 std::unique_ptr<CommandMQ> tempCommandMQ;
1166 std::unique_ptr<DataMQ> tempDataMQ;
1167 std::unique_ptr<StatusMQ> tempStatusMQ;
1168 Result retval;
1169 Return<void> ret = mStream->prepareForReading(
1170 1, mBufferSize,
1171 [&](Result r, const CommandMQ::Descriptor& commandMQ,
1172 const DataMQ::Descriptor& dataMQ, const StatusMQ::Descriptor& statusMQ,
1173 const auto& /*halThreadInfo*/) {
1174 retval = r;
1175 if (retval == Result::OK) {
1176 tempCommandMQ.reset(new CommandMQ(commandMQ));
1177 tempDataMQ.reset(new DataMQ(dataMQ));
1178 tempStatusMQ.reset(new StatusMQ(statusMQ));
1179 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
1180 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
1181 }
1182 }
1183 });
1184 if (!ret.isOk()) {
1185 ALOGE("Transport error while calling prepareForReading: %s", ret.description().c_str());
1186 return false;
1187 }
1188 if (retval != Result::OK) {
1189 ALOGE("Error from prepareForReading: %d", retval);
1190 return false;
1191 }
1192 if (!tempCommandMQ || !tempCommandMQ->isValid() || !tempDataMQ || !tempDataMQ->isValid() ||
1193 !tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
1194 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for reading");
1195 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
1196 "Command message queue for reading is invalid");
1197 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
1198 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(),
1199 "Data message queue for reading is invalid");
1200 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
1201 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
1202 "Status message queue for reading is invalid");
1203 ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
1204 return false;
1205 }
1206 mCommandMQ = std::move(tempCommandMQ);
1207 mDataMQ = std::move(tempDataMQ);
1208 mStatusMQ = std::move(tempStatusMQ);
1209 return true;
1210 }
1211
workerCycle()1212 bool workerCycle() {
1213 ReadParameters params;
1214 params.command = IStreamIn::ReadCommand::READ;
1215 params.params.read = mBufferSize;
1216 if (!mCommandMQ->write(¶ms)) {
1217 ALOGE("command message queue write failed");
1218 return false;
1219 }
1220 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
1221
1222 uint32_t efState = 0;
1223 bool success = true;
1224 retry:
1225 status_t ret =
1226 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
1227 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
1228 ReadStatus readStatus;
1229 readStatus.retval = Result::NOT_INITIALIZED;
1230 if (!mStatusMQ->read(&readStatus)) {
1231 ALOGE("status message read failed");
1232 success = false;
1233 }
1234 if (readStatus.retval != Result::OK) {
1235 ALOGE("bad read status: %d", readStatus.retval);
1236 success = false;
1237 }
1238 const size_t dataSize = std::min(mData.size(), mDataMQ->availableToRead());
1239 if (!mDataMQ->read(mData.data(), dataSize)) {
1240 ALOGE("data message queue read failed");
1241 success = false;
1242 }
1243 }
1244 if (ret == -EAGAIN || ret == -EINTR) {
1245 // Spurious wakeup. This normally retries no more than once.
1246 goto retry;
1247 } else if (ret) {
1248 ALOGE("bad wait status: %d", ret);
1249 success = false;
1250 }
1251 return success;
1252 }
1253
1254 private:
1255 IStreamIn* const mStream;
1256 const size_t mBufferSize;
1257 std::vector<uint8_t> mData;
1258 std::unique_ptr<CommandMQ> mCommandMQ;
1259 std::unique_ptr<DataMQ> mDataMQ;
1260 std::unique_ptr<StatusMQ> mStatusMQ;
1261 EventFlag* mEfGroup = nullptr;
1262 };
1263
1264 class InputStreamTest
1265 : public OpenStreamTest<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> {
SetUp()1266 void SetUp() override {
1267 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
1268 auto flags = getInputFlags();
1269 #if MAJOR_VERSION <= 6
1270 address.device = AudioDevice::IN_DEFAULT;
1271 #elif MAJOR_VERSION >= 7
1272 address = getAttachedDeviceAddress();
1273 auto& metadata = initMetadata.tracks[0];
1274 if (!xsd::isTelephonyDevice(address.deviceType)) {
1275 metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
1276 metadata.channelMask = getConfig().base.channelMask;
1277 } else {
1278 address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
1279 }
1280 #if MAJOR_VERSION == 7 && MINOR_VERSION >= 1
1281 auto flagsIt = std::find(flags.begin(), flags.end(),
1282 toString(xsd::AudioInOutFlag::AUDIO_INPUT_FLAG_ULTRASOUND));
1283 if (flagsIt != flags.end()) {
1284 metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_ULTRASOUND);
1285 }
1286 #endif // 7.1
1287 #endif // MAJOR_VERSION >= 7
1288 const AudioConfig& config = getConfig();
1289 testOpen(
1290 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
1291 return getDevice()->openInputStream(handle, address, config, flags,
1292 initMetadata, cb);
1293 },
1294 config);
1295 }
1296
1297 protected:
1298 #if MAJOR_VERSION == 2
1299 const AudioSource initMetadata = AudioSource::DEFAULT;
1300 #elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
1301 const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
1302 #elif MAJOR_VERSION >= 7
1303 const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
1304 SinkMetadata initMetadata = {
1305 {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT),
1306 .gain = 1,
1307 .tags = {},
1308 .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
1309 #endif
1310 };
1311
TEST_P(InputStreamTest,OpenInputStreamTest)1312 TEST_P(InputStreamTest, OpenInputStreamTest) {
1313 doc::test(
1314 "Check that input streams can be open with the required and "
1315 "recommended config");
1316 // Open done in setup
1317 }
1318 #if MAJOR_VERSION <= 5
1319 // For V2..5 test the primary device according to CDD requirements.
1320 INSTANTIATE_TEST_CASE_P(
1321 RequiredInputStreamConfigSupport, InputStreamTest,
1322 ::testing::Combine(
1323 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1324 ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()),
1325 ::testing::Values(AudioInputFlag::NONE)),
1326 &DeviceConfigParameterToString);
1327 INSTANTIATE_TEST_CASE_P(
1328 RecommendedInputStreamConfigSupport, InputStreamTest,
1329 ::testing::Combine(
1330 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1331 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
1332 ::testing::Values(AudioInputFlag::NONE)),
1333 &DeviceConfigParameterToString);
1334 #elif MAJOR_VERSION >= 6
1335 // For V6 and above test according to the audio policy manager configuration.
1336 // This is more correct as CDD is written from the apps perspective.
1337 // Audio system provides necessary format conversions for missing configurations.
1338 INSTANTIATE_TEST_CASE_P(DeclaredInputStreamConfigSupport, InputStreamTest,
1339 ::testing::ValuesIn(getInputDeviceConfigParameters()),
1340 &DeviceConfigParameterToString);
1341 #endif
1342 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
1343 // list is empty, this isn't a problem.
1344 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamTest);
1345
1346 //////////////////////////////////////////////////////////////////////////////
1347 ////////////////////////////// IStream getters ///////////////////////////////
1348 //////////////////////////////////////////////////////////////////////////////
1349
1350 /* Could not find a way to write a test for two parametrized class fixure
1351 * thus use this macro do duplicate tests for Input and Output stream */
1352 #define TEST_IO_STREAM(test_name, documentation, code) \
1353 TEST_P(InputStreamTest, test_name) { \
1354 doc::test(documentation); \
1355 code; \
1356 } \
1357 TEST_P(OutputStreamTest, test_name) { \
1358 doc::test(documentation); \
1359 code; \
1360 }
1361
1362 TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
1363 ASSERT_TRUE(stream->getFrameCount().isOk()))
1364
1365 #if MAJOR_VERSION <= 6
1366 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
1367 ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
1368
1369 TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it was opened with",
1370 ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask())))
1371
1372 TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
1373 ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
1374 #endif
1375
1376 // TODO: for now only check that the framesize is not incoherent
1377 TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
1378 ASSERT_GT(extract(stream->getFrameSize()), 0U))
1379
1380 TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it was opened with",
1381 ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize())));
1382
1383 template <class Property, class CapabilityGetter>
1384 static void testCapabilityGetter(const std::string& name, IStream* stream,
1385 CapabilityGetter capabilityGetter,
1386 Return<Property> (IStream::*getter)(),
1387 Return<Result> (IStream::*setter)(Property),
1388 bool currentMustBeSupported = true) {
1389 hidl_vec<Property> capabilities;
1390 auto ret = capabilityGetter(stream, capabilities);
1391 ASSERT_RESULT(okOrNotSupported, ret);
1392 bool notSupported = ret == Result::NOT_SUPPORTED;
1393 if (notSupported) {
1394 doc::partialTest(name + " is not supported");
1395 return;
1396 };
1397
1398 if (currentMustBeSupported) {
1399 ASSERT_NE(0U, capabilities.size()) << name << " must not return an empty list";
1400 Property currentValue = extract((stream->*getter)());
1401 EXPECT_TRUE(std::find(capabilities.begin(), capabilities.end(), currentValue) !=
1402 capabilities.end())
1403 << "value returned by " << name << "() = " << testing::PrintToString(currentValue)
1404 << " is not in the list of the supported ones " << toString(capabilities);
1405 }
1406
1407 // Check that all declared supported values are indeed supported
1408 for (auto capability : capabilities) {
1409 auto ret = (stream->*setter)(capability);
1410 ASSERT_TRUE(ret.isOk());
1411 if (ret == Result::NOT_SUPPORTED) {
1412 doc::partialTest("Setter is not supported");
1413 return;
1414 }
1415 ASSERT_OK(ret);
1416 ASSERT_EQ(capability, extract((stream->*getter)()));
1417 }
1418 }
1419
1420 #if MAJOR_VERSION <= 6
1421 TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
1422 testCapabilityGetter("getSupportedSampleRate", stream.get(),
1423 &GetSupported::sampleRates, &IStream::getSampleRate,
1424 &IStream::setSampleRate,
1425 // getSupportedSampleRate returns the native sampling rates,
1426 // (the sampling rates that can be played without resampling)
1427 // but other sampling rates can be supported by the HAL.
1428 false))
1429
1430 TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is declared as supported",
1431 testCapabilityGetter("getSupportedChannelMask", stream.get(),
1432 &GetSupported::channelMasks, &IStream::getChannelMask,
1433 &IStream::setChannelMask))
1434
1435 TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
1436 testCapabilityGetter("getSupportedFormat", stream.get(), &GetSupported::formats,
1437 &IStream::getFormat, &IStream::setFormat))
1438 #else
1439 static void testGetSupportedProfiles(IStream* stream) {
1440 Result res;
1441 hidl_vec<AudioProfile> profiles;
1442 auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
1443 EXPECT_TRUE(ret.isOk());
1444 if (res == Result::OK) {
1445 EXPECT_GT(profiles.size(), 0);
1446 } else {
1447 EXPECT_EQ(Result::NOT_SUPPORTED, res);
1448 }
1449 }
1450
1451 TEST_IO_STREAM(GetSupportedProfiles, "Try to call optional method GetSupportedProfiles",
1452 testGetSupportedProfiles(stream.get()))
1453
1454 static void testSetAudioProperties(IStream* stream) {
1455 Result res;
1456 hidl_vec<AudioProfile> profiles;
1457 auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
1458 EXPECT_TRUE(ret.isOk());
1459 if (res == Result::NOT_SUPPORTED) {
1460 GTEST_SKIP() << "Retrieving supported profiles is not implemented";
1461 }
1462 for (const auto& profile : profiles) {
1463 for (const auto& sampleRate : profile.sampleRates) {
1464 for (const auto& channelMask : profile.channelMasks) {
1465 AudioConfigBaseOptional config;
1466 config.format.value(profile.format);
1467 config.sampleRateHz.value(sampleRate);
1468 config.channelMask.value(channelMask);
1469 auto ret = stream->setAudioProperties(config);
1470 EXPECT_TRUE(ret.isOk());
1471 if (ret == Result::NOT_SUPPORTED) {
1472 GTEST_SKIP() << "setAudioProperties is not supported";
1473 }
1474 EXPECT_EQ(Result::OK, ret)
1475 << profile.format << "; " << sampleRate << "; " << channelMask;
1476 }
1477 }
1478 }
1479 }
1480
1481 TEST_IO_STREAM(SetAudioProperties, "Call setAudioProperties for all supported profiles",
1482 testSetAudioProperties(stream.get()))
1483 #endif // MAJOR_VERSION <= 6
1484
testGetAudioProperties(IStream * stream,AudioConfig expectedConfig)1485 static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
1486 #if MAJOR_VERSION <= 6
1487 uint32_t sampleRateHz;
1488 auto mask = mkEnumBitfield<AudioChannelMask>({});
1489 AudioFormat format;
1490
1491 auto ret = stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
1492 EXPECT_TRUE(ret.isOk());
1493
1494 // FIXME: the qcom hal it does not currently negotiate the sampleRate &
1495 // channel mask
1496 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
1497 EXPECT_EQ(expectedConfig.channelMask, mask);
1498 EXPECT_EQ(expectedConfig.format, format);
1499 #elif MAJOR_VERSION >= 7
1500 Result res;
1501 AudioConfigBase actualConfig{};
1502 auto ret = stream->getAudioProperties(returnIn(res, actualConfig));
1503 EXPECT_TRUE(ret.isOk());
1504 EXPECT_EQ(Result::OK, res);
1505 EXPECT_EQ(expectedConfig.base.sampleRateHz, actualConfig.sampleRateHz);
1506 EXPECT_EQ(expectedConfig.base.channelMask, actualConfig.channelMask);
1507 EXPECT_EQ(expectedConfig.base.format, actualConfig.format);
1508 #endif
1509 }
1510
1511 TEST_IO_STREAM(GetAudioProperties,
1512 "Check that the stream audio properties == the ones it was opened with",
1513 testGetAudioProperties(stream.get(), audioConfig))
1514
1515 TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value",
1516 ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, stream->setHwAvSync(666)))
1517
checkGetNoParameter(IStream * stream,hidl_vec<hidl_string> keys,std::initializer_list<Result> expectedResults)1518 static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
1519 std::initializer_list<Result> expectedResults) {
1520 hidl_vec<ParameterValue> parameters;
1521 Result res;
1522 ASSERT_OK(Parameters::get(stream, keys, returnIn(res, parameters)));
1523 ASSERT_RESULT(expectedResults, res);
1524 if (res == Result::OK) {
1525 for (auto& parameter : parameters) {
1526 ASSERT_EQ(0U, parameter.value.size()) << toString(parameter);
1527 }
1528 }
1529 }
1530
1531 /* Get/Set parameter is intended to be an opaque channel between vendors app and
1532 * their HALs.
1533 * Thus can not be meaningfully tested.
1534 */
1535 TEST_IO_STREAM(getEmptySetParameter, "Retrieve the values of an empty set",
1536 checkGetNoParameter(stream.get(), {} /* keys */, {Result::OK}))
1537
1538 TEST_IO_STREAM(getNonExistingParameter, "Retrieve the values of an non existing parameter",
1539 checkGetNoParameter(stream.get(), {"Non existing key"} /* keys */,
1540 {Result::NOT_SUPPORTED}))
1541
1542 TEST_IO_STREAM(setEmptySetParameter, "Set the values of an empty set of parameters",
1543 ASSERT_RESULT(Result::OK, Parameters::set(stream, {})))
1544
1545 TEST_IO_STREAM(setNonExistingParameter, "Set the values of an non existing parameter",
1546 // Unfortunately, the set_parameter legacy interface did not return any
1547 // error code when a key is not supported.
1548 // To allow implementation to just wrapped the legacy one, consider OK as a
1549 // valid result for setting a non existing parameter.
1550 ASSERT_RESULT(okOrNotSupportedOrInvalidArgs,
1551 Parameters::set(stream, {{"non existing key", "0"}})))
1552
1553 TEST_IO_STREAM(DebugDump, "Check that a stream can dump its state without error",
1554 testDebugDump([this](const auto& handle) { return dump(stream, handle); }))
1555
1556 TEST_IO_STREAM(DebugDumpInvalidArguments,
1557 "Check that the stream dump doesn't crash on invalid arguments",
1558 ASSERT_OK(dump(stream, hidl_handle())))
1559
1560 //////////////////////////////////////////////////////////////////////////////
1561 ////////////////////////////// addRemoveEffect ///////////////////////////////
1562 //////////////////////////////////////////////////////////////////////////////
1563
1564 TEST_IO_STREAM(AddNonExistingEffect, "Adding a non existing effect should fail",
1565 ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->addEffect(666)))
1566 TEST_IO_STREAM(RemoveNonExistingEffect, "Removing a non existing effect should fail",
1567 ASSERT_RESULT(Result::INVALID_ARGUMENTS, stream->removeEffect(666)))
1568
1569 // TODO: positive tests
1570
1571 //////////////////////////////////////////////////////////////////////////////
1572 /////////////////////////////// Control ////////////////////////////////
1573 //////////////////////////////////////////////////////////////////////////////
1574
1575 TEST_IO_STREAM(standby, "Make sure the stream can be put in stanby",
1576 ASSERT_OK(stream->standby())) // can not fail
1577
1578 TEST_IO_STREAM(startNoMmap, "Starting a mmaped stream before mapping it should fail",
1579 ASSERT_RESULT(invalidStateOrNotSupported, stream->start()))
1580
1581 TEST_IO_STREAM(stopNoMmap, "Stopping a mmaped stream before mapping it should fail",
1582 ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
1583
1584 TEST_IO_STREAM(getMmapPositionNoMmap, "Get a stream Mmap position before mapping it should fail",
1585 ASSERT_RESULT(invalidStateOrNotSupported, stream->stop()))
1586
1587 TEST_IO_STREAM(close, "Make sure a stream can be closed", ASSERT_OK(closeStream()))
1588 // clang-format off
1589 TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice",
1590 ASSERT_OK(closeStream(false /*clear*/));
1591 ASSERT_EQ(Result::INVALID_STATE, closeStream()))
1592 // clang-format on
1593
testMmapBufferOfInvalidSize(IStream * stream)1594 static void testMmapBufferOfInvalidSize(IStream* stream) {
1595 for (int32_t value : {-1, 0, std::numeric_limits<int32_t>::max()}) {
1596 MmapBufferInfo info;
1597 Result res;
1598 EXPECT_OK(stream->createMmapBuffer(value, returnIn(res, info)));
1599 EXPECT_RESULT(invalidArgsOrNotSupported, res) << "value=" << value;
1600 }
1601 }
1602
1603 TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer of invalid size must fail",
1604 testMmapBufferOfInvalidSize(stream.get()))
1605
testGetMmapPositionOfNonMmapedStream(IStream * stream)1606 static void testGetMmapPositionOfNonMmapedStream(IStream* stream) {
1607 Result res;
1608 MmapPosition position;
1609 ASSERT_OK(stream->getMmapPosition(returnIn(res, position)));
1610 ASSERT_RESULT(invalidArgsOrNotSupported, res);
1611 }
1612
1613 TEST_IO_STREAM(GetMmapPositionOfNonMmapedStream,
1614 "Retrieving the mmap position of a non mmaped stream should fail",
1615 testGetMmapPositionOfNonMmapedStream(stream.get()))
1616
1617 //////////////////////////////////////////////////////////////////////////////
1618 ///////////////////////////////// StreamIn ///////////////////////////////////
1619 //////////////////////////////////////////////////////////////////////////////
1620
TEST_P(InputStreamTest,GetAudioSource)1621 TEST_P(InputStreamTest, GetAudioSource) {
1622 doc::test("Retrieving the audio source of an input stream should always succeed");
1623 AudioSource source;
1624 ASSERT_OK(stream->getAudioSource(returnIn(res, source)));
1625 if (res == Result::NOT_SUPPORTED) {
1626 doc::partialTest("getAudioSource is not supported");
1627 return;
1628 }
1629 ASSERT_OK(res);
1630 #if MAJOR_VERSION <= 6
1631 ASSERT_EQ(AudioSource::DEFAULT, source);
1632 #elif MAJOR_VERSION >= 7
1633 ASSERT_EQ(xsd::AudioSource::AUDIO_SOURCE_DEFAULT, xsd::stringToAudioSource(source));
1634 #endif
1635 }
1636
testUnitaryGain(std::function<Return<Result> (float)> setGain)1637 static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
1638 for (float value : (float[]){-INFINITY, -1.0, 1.0 + std::numeric_limits<float>::epsilon(), 2.0,
1639 INFINITY, NAN}) {
1640 EXPECT_RESULT(Result::INVALID_ARGUMENTS, setGain(value)) << "value=" << value;
1641 }
1642 // Do not consider -0.0 as an invalid value as it is == with 0.0
1643 for (float value : {-0.0, 0.0, 0.01, 0.5, 0.09, 1.0 /* Restore volume*/}) {
1644 EXPECT_OK(setGain(value)) << "value=" << value;
1645 }
1646 }
1647
testOptionalUnitaryGain(std::function<Return<Result> (float)> setGain,std::string debugName)1648 static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
1649 std::string debugName) {
1650 auto result = setGain(1);
1651 ASSERT_IS_OK(result);
1652 if (result == Result::NOT_SUPPORTED) {
1653 doc::partialTest(debugName + " is not supported");
1654 return;
1655 }
1656 testUnitaryGain(setGain);
1657 }
1658
TEST_P(InputStreamTest,SetGain)1659 TEST_P(InputStreamTest, SetGain) {
1660 doc::test("The gain of an input stream should only be set between [0,1]");
1661 testOptionalUnitaryGain([this](float volume) { return stream->setGain(volume); },
1662 "InputStream::setGain");
1663 }
1664
testPrepareForReading(::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn * stream,uint32_t frameSize,uint32_t framesCount)1665 static void testPrepareForReading(
1666 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn* stream, uint32_t frameSize,
1667 uint32_t framesCount) {
1668 Result res;
1669 // Ignore output parameters as the call should fail
1670 ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
1671 [&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
1672 EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
1673 }
1674
TEST_P(InputStreamTest,PrepareForReadingWithZeroBuffer)1675 TEST_P(InputStreamTest, PrepareForReadingWithZeroBuffer) {
1676 doc::test("Preparing a stream for reading with a 0 sized buffer should fail");
1677 testPrepareForReading(stream.get(), 0, 0);
1678 }
1679
TEST_P(InputStreamTest,PrepareForReadingWithHugeBuffer)1680 TEST_P(InputStreamTest, PrepareForReadingWithHugeBuffer) {
1681 doc::test("Preparing a stream for reading with a 2^32 sized buffer should fail");
1682 testPrepareForReading(stream.get(), 1, std::numeric_limits<uint32_t>::max());
1683 }
1684
TEST_P(InputStreamTest,PrepareForReadingCheckOverflow)1685 TEST_P(InputStreamTest, PrepareForReadingCheckOverflow) {
1686 doc::test(
1687 "Preparing a stream for reading with a overflowing sized buffer should "
1688 "fail");
1689 auto uintMax = std::numeric_limits<uint32_t>::max();
1690 testPrepareForReading(stream.get(), uintMax, uintMax);
1691 }
1692
TEST_P(InputStreamTest,GetInputFramesLost)1693 TEST_P(InputStreamTest, GetInputFramesLost) {
1694 doc::test("The number of frames lost on a never started stream should be 0");
1695 auto ret = stream->getInputFramesLost();
1696 ASSERT_IS_OK(ret);
1697 uint32_t framesLost{ret};
1698 ASSERT_EQ(0U, framesLost);
1699 }
1700
1701 //////////////////////////////////////////////////////////////////////////////
1702 ///////////////////////////////// StreamOut //////////////////////////////////
1703 //////////////////////////////////////////////////////////////////////////////
1704
TEST_P(OutputStreamTest,getLatency)1705 TEST_P(OutputStreamTest, getLatency) {
1706 doc::test("Make sure latency is over 0");
1707 auto result = stream->getLatency();
1708 ASSERT_IS_OK(result);
1709 ASSERT_GT(result, 0U);
1710 }
1711
TEST_P(OutputStreamTest,setVolume)1712 TEST_P(OutputStreamTest, setVolume) {
1713 doc::test("Try to set the output volume");
1714 testOptionalUnitaryGain([this](float volume) { return stream->setVolume(volume, volume); },
1715 "setVolume");
1716 }
1717
testPrepareForWriting(::android::hardware::audio::CPP_VERSION::IStreamOut * stream,uint32_t frameSize,uint32_t framesCount)1718 static void testPrepareForWriting(::android::hardware::audio::CPP_VERSION::IStreamOut* stream,
1719 uint32_t frameSize, uint32_t framesCount) {
1720 Result res;
1721 // Ignore output parameters as the call should fail
1722 ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
1723 [&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
1724 EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
1725 }
1726
TEST_P(OutputStreamTest,PrepareForWriteWithZeroBuffer)1727 TEST_P(OutputStreamTest, PrepareForWriteWithZeroBuffer) {
1728 doc::test("Preparing a stream for writing with a 0 sized buffer should fail");
1729 testPrepareForWriting(stream.get(), 0, 0);
1730 }
1731
TEST_P(OutputStreamTest,PrepareForWriteWithHugeBuffer)1732 TEST_P(OutputStreamTest, PrepareForWriteWithHugeBuffer) {
1733 doc::test("Preparing a stream for writing with a 2^32 sized buffer should fail");
1734 testPrepareForWriting(stream.get(), 1, std::numeric_limits<uint32_t>::max());
1735 }
1736
TEST_P(OutputStreamTest,PrepareForWritingCheckOverflow)1737 TEST_P(OutputStreamTest, PrepareForWritingCheckOverflow) {
1738 doc::test(
1739 "Preparing a stream for writing with a overflowing sized buffer should "
1740 "fail");
1741 auto uintMax = std::numeric_limits<uint32_t>::max();
1742 testPrepareForWriting(stream.get(), uintMax, uintMax);
1743 }
1744
1745 struct Capability {
1746 using IStreamOut = ::android::hardware::audio::CPP_VERSION::IStreamOut;
1747
CapabilityCapability1748 Capability(IStreamOut* stream) {
1749 EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume)));
1750 drain = extract(stream->supportsDrain());
1751 }
1752 bool pause = false;
1753 bool resume = false;
1754 bool drain = false;
1755 };
1756
TEST_P(OutputStreamTest,SupportsPauseAndResumeAndDrain)1757 TEST_P(OutputStreamTest, SupportsPauseAndResumeAndDrain) {
1758 doc::test("Implementation must expose pause, resume and drain capabilities");
1759 Capability(stream.get());
1760 }
1761
TEST_P(OutputStreamTest,GetRenderPosition)1762 TEST_P(OutputStreamTest, GetRenderPosition) {
1763 doc::test("A new stream render position should be 0 or INVALID_STATE");
1764 uint32_t dspFrames;
1765 ASSERT_OK(stream->getRenderPosition(returnIn(res, dspFrames)));
1766 if (res == Result::NOT_SUPPORTED) {
1767 doc::partialTest("getRenderPosition is not supported");
1768 return;
1769 }
1770 expectValueOrFailure(res, 0U, dspFrames, Result::INVALID_STATE);
1771 }
1772
TEST_P(OutputStreamTest,GetNextWriteTimestamp)1773 TEST_P(OutputStreamTest, GetNextWriteTimestamp) {
1774 doc::test("A new stream next write timestamp should be 0 or INVALID_STATE");
1775 uint64_t timestampUs;
1776 ASSERT_OK(stream->getNextWriteTimestamp(returnIn(res, timestampUs)));
1777 if (res == Result::NOT_SUPPORTED) {
1778 doc::partialTest("getNextWriteTimestamp is not supported");
1779 return;
1780 }
1781 expectValueOrFailure(res, uint64_t{0}, timestampUs, Result::INVALID_STATE);
1782 }
1783
1784 /** Stub implementation of out stream callback. */
1785 class MockOutCallbacks : public IStreamOutCallback {
onWriteReady()1786 Return<void> onWriteReady() override { return {}; }
onDrainReady()1787 Return<void> onDrainReady() override { return {}; }
onError()1788 Return<void> onError() override { return {}; }
1789 };
1790
isAsyncModeSupported(::android::hardware::audio::CPP_VERSION::IStreamOut * stream)1791 static bool isAsyncModeSupported(::android::hardware::audio::CPP_VERSION::IStreamOut* stream) {
1792 auto res = stream->setCallback(new MockOutCallbacks);
1793 stream->clearCallback(); // try to restore the no callback state, ignore
1794 // any error
1795 EXPECT_RESULT(okOrNotSupported, res);
1796 return res.isOk() ? res == Result::OK : false;
1797 }
1798
TEST_P(OutputStreamTest,SetCallback)1799 TEST_P(OutputStreamTest, SetCallback) {
1800 doc::test(
1801 "If supported, registering callback for async operation should never "
1802 "fail");
1803 if (!isAsyncModeSupported(stream.get())) {
1804 doc::partialTest("The stream does not support async operations");
1805 return;
1806 }
1807 ASSERT_OK(stream->setCallback(new MockOutCallbacks));
1808 ASSERT_OK(stream->setCallback(new MockOutCallbacks));
1809 }
1810
TEST_P(OutputStreamTest,clearCallback)1811 TEST_P(OutputStreamTest, clearCallback) {
1812 doc::test(
1813 "If supported, clearing a callback to go back to sync operation should "
1814 "not fail");
1815 if (!isAsyncModeSupported(stream.get())) {
1816 doc::partialTest("The stream does not support async operations");
1817 return;
1818 }
1819 // TODO: Clarify if clearing a non existing callback should fail
1820 ASSERT_OK(stream->setCallback(new MockOutCallbacks));
1821 ASSERT_OK(stream->clearCallback());
1822 }
1823
TEST_P(OutputStreamTest,Resume)1824 TEST_P(OutputStreamTest, Resume) {
1825 doc::test(
1826 "If supported, a stream should fail to resume if not previously "
1827 "paused");
1828 if (!Capability(stream.get()).resume) {
1829 doc::partialTest("The output stream does not support resume");
1830 return;
1831 }
1832 ASSERT_RESULT(Result::INVALID_STATE, stream->resume());
1833 }
1834
TEST_P(OutputStreamTest,Pause)1835 TEST_P(OutputStreamTest, Pause) {
1836 doc::test(
1837 "If supported, a stream should fail to pause if not previously "
1838 "started");
1839 if (!Capability(stream.get()).pause) {
1840 doc::partialTest("The output stream does not support pause");
1841 return;
1842 }
1843 ASSERT_RESULT(Result::INVALID_STATE, stream->pause());
1844 }
1845
testDrain(::android::hardware::audio::CPP_VERSION::IStreamOut * stream,AudioDrain type)1846 static void testDrain(::android::hardware::audio::CPP_VERSION::IStreamOut* stream,
1847 AudioDrain type) {
1848 if (!Capability(stream).drain) {
1849 doc::partialTest("The output stream does not support drain");
1850 return;
1851 }
1852 ASSERT_RESULT(Result::OK, stream->drain(type));
1853 }
1854
TEST_P(OutputStreamTest,DrainAll)1855 TEST_P(OutputStreamTest, DrainAll) {
1856 doc::test("If supported, a stream should always succeed to drain");
1857 testDrain(stream.get(), AudioDrain::ALL);
1858 }
1859
TEST_P(OutputStreamTest,DrainEarlyNotify)1860 TEST_P(OutputStreamTest, DrainEarlyNotify) {
1861 doc::test("If supported, a stream should always succeed to drain");
1862 testDrain(stream.get(), AudioDrain::EARLY_NOTIFY);
1863 }
1864
TEST_P(OutputStreamTest,FlushStop)1865 TEST_P(OutputStreamTest, FlushStop) {
1866 doc::test("If supported, a stream should always succeed to flush");
1867 auto ret = stream->flush();
1868 ASSERT_IS_OK(ret);
1869 if (ret == Result::NOT_SUPPORTED) {
1870 doc::partialTest("Flush is not supported");
1871 return;
1872 }
1873 ASSERT_OK(ret);
1874 }
1875
TEST_P(OutputStreamTest,GetPresentationPositionStop)1876 TEST_P(OutputStreamTest, GetPresentationPositionStop) {
1877 doc::test(
1878 "If supported, a stream should always succeed to retrieve the "
1879 "presentation position");
1880 uint64_t frames;
1881 TimeSpec measureTS;
1882 ASSERT_OK(stream->getPresentationPosition(returnIn(res, frames, measureTS)));
1883 #if MAJOR_VERSION <= 6
1884 if (res == Result::NOT_SUPPORTED) {
1885 doc::partialTest("getPresentationPosition is not supported");
1886 return;
1887 }
1888 #else
1889 ASSERT_NE(Result::NOT_SUPPORTED, res) << "getPresentationPosition is mandatory in V7";
1890 #endif
1891 ASSERT_EQ(0U, frames);
1892
1893 if (measureTS.tvNSec == 0 && measureTS.tvSec == 0) {
1894 // As the stream has never written a frame yet,
1895 // the timestamp does not really have a meaning, allow to return 0
1896 return;
1897 }
1898
1899 // Make sure the return measure is not more than 1s old.
1900 struct timespec currentTS;
1901 ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤tTS)) << errno;
1902
1903 auto toMicroSec = [](uint64_t sec, auto nsec) { return sec * 1e+6 + nsec / 1e+3; };
1904 auto currentTime = toMicroSec(currentTS.tv_sec, currentTS.tv_nsec);
1905 auto measureTime = toMicroSec(measureTS.tvSec, measureTS.tvNSec);
1906 ASSERT_PRED2([](auto c, auto m) { return c - m < 1e+6; }, currentTime, measureTime);
1907 }
1908
1909 //////////////////////////////////////////////////////////////////////////////
1910 /////////////////////////////// PrimaryDevice ////////////////////////////////
1911 //////////////////////////////////////////////////////////////////////////////
1912
TEST_P(AudioPrimaryHidlTest,setVoiceVolume)1913 TEST_P(AudioPrimaryHidlTest, setVoiceVolume) {
1914 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
1915 testUnitaryGain([this](float volume) { return getDevice()->setVoiceVolume(volume); });
1916 }
1917
TEST_P(BoolAccessorPrimaryHidlTest,BtScoNrecEnabled)1918 TEST_P(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
1919 doc::test("Query and set the BT SCO NR&EC state");
1920 testAccessors<OPTIONAL>("BtScoNrecEnabled", Initial{false, OPTIONAL}, {true},
1921 &IPrimaryDevice::setBtScoNrecEnabled,
1922 &IPrimaryDevice::getBtScoNrecEnabled);
1923 }
1924
TEST_P(BoolAccessorPrimaryHidlTest,setGetBtScoWidebandEnabled)1925 TEST_P(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
1926 doc::test("Query and set the SCO whideband state");
1927 testAccessors<OPTIONAL>("BtScoWideband", Initial{false, OPTIONAL}, {true},
1928 &IPrimaryDevice::setBtScoWidebandEnabled,
1929 &IPrimaryDevice::getBtScoWidebandEnabled);
1930 }
1931
1932 using TtyModeAccessorPrimaryHidlTest =
1933 AccessorHidlTest<::android::hardware::audio::CPP_VERSION::IPrimaryDevice::TtyMode,
1934 AudioPrimaryHidlTest>;
TEST_P(TtyModeAccessorPrimaryHidlTest,setGetTtyMode)1935 TEST_P(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
1936 doc::test("Query and set the TTY mode state");
1937 testAccessors<OPTIONAL>(
1938 "TTY mode", Initial{IPrimaryDevice::TtyMode::OFF},
1939 {IPrimaryDevice::TtyMode::HCO, IPrimaryDevice::TtyMode::VCO, IPrimaryDevice::TtyMode::FULL},
1940 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
1941 }
1942 INSTANTIATE_TEST_CASE_P(TtyModeAccessorPrimaryHidl, TtyModeAccessorPrimaryHidlTest,
1943 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
1944 &DeviceParameterToString);
1945 // When the VTS test runs on a device lacking the corresponding HAL version the parameter
1946 // list is empty, this isn't a problem.
1947 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TtyModeAccessorPrimaryHidlTest);
1948
TEST_P(BoolAccessorPrimaryHidlTest,setGetHac)1949 TEST_P(BoolAccessorPrimaryHidlTest, setGetHac) {
1950 doc::test("Query and set the HAC state");
1951 testAccessors<OPTIONAL>("HAC", Initial{false}, {true}, &IPrimaryDevice::setHacEnabled,
1952 &IPrimaryDevice::getHacEnabled);
1953 }
1954