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