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