blob: a3f0d275f06a8b359b57f79c0cc801f8ff46d7c1 [file] [log] [blame]
Kevin Rocardf0357882017-02-10 16:19:28 -08001/*
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 <list>
25#include <string>
26#include <type_traits>
27#include <vector>
28
29#include <gtest/gtest.h>
30
31#include <android-base/logging.h>
32
33#include <android/hardware/audio/2.0/IDevice.h>
34#include <android/hardware/audio/2.0/IDevicesFactory.h>
Kevin Rocard3c405a72017-03-08 16:46:51 -080035#include <android/hardware/audio/2.0/IPrimaryDevice.h>
Kevin Rocardf0357882017-02-10 16:19:28 -080036#include <android/hardware/audio/2.0/types.h>
37#include <android/hardware/audio/common/2.0/types.h>
38
39#include "utility/ReturnIn.h"
40#include "utility/AssertOk.h"
41#include "utility/PrettyPrintAudioTypes.h"
42
43using std::string;
44using std::to_string;
45using std::vector;
46
47using ::android::sp;
48using ::android::hardware::Return;
49using ::android::hardware::hidl_handle;
50using ::android::hardware::hidl_string;
51using ::android::hardware::hidl_vec;
52using ::android::hardware::audio::V2_0::DeviceAddress;
53using ::android::hardware::audio::V2_0::IDevice;
Kevin Rocard3c405a72017-03-08 16:46:51 -080054using ::android::hardware::audio::V2_0::IPrimaryDevice;
55using TtyMode = ::android::hardware::audio::V2_0::IPrimaryDevice::TtyMode;
Kevin Rocardf0357882017-02-10 16:19:28 -080056using ::android::hardware::audio::V2_0::IDevicesFactory;
57using ::android::hardware::audio::V2_0::IStream;
58using ::android::hardware::audio::V2_0::IStreamIn;
59using ::android::hardware::audio::V2_0::IStreamOut;
60using ::android::hardware::audio::V2_0::ParameterValue;
61using ::android::hardware::audio::V2_0::Result;
62using ::android::hardware::audio::common::V2_0::AudioChannelMask;
63using ::android::hardware::audio::common::V2_0::AudioConfig;
64using ::android::hardware::audio::common::V2_0::AudioDevice;
65using ::android::hardware::audio::common::V2_0::AudioFormat;
66using ::android::hardware::audio::common::V2_0::AudioHandleConsts;
67using ::android::hardware::audio::common::V2_0::AudioInputFlag;
68using ::android::hardware::audio::common::V2_0::AudioIoHandle;
Kevin Rocard3c405a72017-03-08 16:46:51 -080069using ::android::hardware::audio::common::V2_0::AudioMode;
Kevin Rocardf0357882017-02-10 16:19:28 -080070using ::android::hardware::audio::common::V2_0::AudioOffloadInfo;
71using ::android::hardware::audio::common::V2_0::AudioOutputFlag;
72using ::android::hardware::audio::common::V2_0::AudioSource;
73
74using utility::returnIn;
75
76namespace doc {
77/** Document the current test case.
78 * Eg: calling `doc::test("Dump the state of the hal")` in the "debugDump" test will output:
79 * <testcase name="debugDump" status="run" time="6" classname="AudioPrimaryHidlTest"
80 description="Dump the state of the hal." />
81 * see https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#logging-additional-information
82 */
83void test(const std::string& testCaseDocumentation) {
84 ::testing::Test::RecordProperty("description", testCaseDocumentation);
85}
86
87/** Document why a test was not fully run. Usually due to an optional feature not implemented. */
88void partialTest(const std::string& reason) {
89 ::testing::Test::RecordProperty("partialyRunTest", reason);
90}
91}
92
93// Register callback for static object destruction
94// Avoid destroying static objects after main return.
95// Post main return destruction leads to incorrect gtest timing measurements as well as harder
96// debuging if anything goes wrong during destruction.
97class Environment : public ::testing::Environment {
98public:
99 using TearDownFunc = std::function<void ()>;
100 void registerTearDown(TearDownFunc&& tearDown) {
101 tearDowns.push_back(std::move(tearDown));
102 }
103
104private:
105 void TearDown() override {
106 // Call the tear downs in reverse order of insertion
107 for (auto& tearDown : tearDowns) {
108 tearDown();
109 }
110 }
111 std::list<TearDownFunc> tearDowns;
112};
113// Instance to register global tearDown
114static Environment* environment;
115
116class HidlTest : public ::testing::Test {
117protected:
118 // Convenient member to store results
119 Result res;
120};
121
122//////////////////////////////////////////////////////////////////////////////
123////////////////////// getService audio_devices_factory //////////////////////
124//////////////////////////////////////////////////////////////////////////////
125
126// Test all audio devices
127class AudioHidlTest : public HidlTest {
128public:
129 void SetUp() override {
130 ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base
131
132 if (devicesFactory == nullptr) {
133 environment->registerTearDown([]{ devicesFactory.clear(); });
134 devicesFactory = IDevicesFactory::getService();
135 }
136 ASSERT_TRUE(devicesFactory != nullptr);
137 }
138
139protected:
140 // Cache the devicesFactory retrieval to speed up each test by ~0.5s
141 static sp<IDevicesFactory> devicesFactory;
142};
143sp<IDevicesFactory> AudioHidlTest::devicesFactory;
144
145TEST_F(AudioHidlTest, GetAudioDevicesFactoryService) {
146 doc::test("test the getService (called in SetUp)");
147}
148
149//////////////////////////////////////////////////////////////////////////////
150/////////////////////////////// openDevice primary ///////////////////////////
151//////////////////////////////////////////////////////////////////////////////
152
153// Test the primary device
154class AudioPrimaryHidlTest : public AudioHidlTest {
155public:
156 /** Primary HAL test are NOT thread safe. */
157 void SetUp() override {
158 ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base
159
160 if (device == nullptr) {
Kevin Rocardf0357882017-02-10 16:19:28 -0800161 IDevicesFactory::Result result;
Kevin Rocard3c405a72017-03-08 16:46:51 -0800162 sp<IDevice> baseDevice;
Kevin Rocardf0357882017-02-10 16:19:28 -0800163 ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY,
Kevin Rocard3c405a72017-03-08 16:46:51 -0800164 returnIn(result, baseDevice)));
165 ASSERT_TRUE(baseDevice != nullptr);
166
167 environment->registerTearDown([]{ device.clear(); });
168 device = IPrimaryDevice::castFrom(baseDevice);
169 ASSERT_TRUE(device != nullptr);
Kevin Rocardf0357882017-02-10 16:19:28 -0800170 }
Kevin Rocardf0357882017-02-10 16:19:28 -0800171 }
172
173protected:
174 // Cache the device opening to speed up each test by ~0.5s
Kevin Rocard3c405a72017-03-08 16:46:51 -0800175 static sp<IPrimaryDevice> device;
Kevin Rocardf0357882017-02-10 16:19:28 -0800176};
Kevin Rocard3c405a72017-03-08 16:46:51 -0800177sp<IPrimaryDevice> AudioPrimaryHidlTest::device;
Kevin Rocardf0357882017-02-10 16:19:28 -0800178
179TEST_F(AudioPrimaryHidlTest, OpenPrimaryDevice) {
180 doc::test("Test the openDevice (called in SetUp)");
181}
182
183TEST_F(AudioPrimaryHidlTest, Init) {
184 doc::test("Test that the audio primary hal initialized correctly");
185 ASSERT_OK(device->initCheck());
186}
187
188//////////////////////////////////////////////////////////////////////////////
189//////////////////////////// {set,get}MasterVolume ///////////////////////////
190//////////////////////////////////////////////////////////////////////////////
191
192class MasterVolumeTest : public AudioPrimaryHidlTest {
193protected:
194 void testSetGetConsistency(float volume, Result expectedSetResult, float expectedGetVolume) {
195 SCOPED_TRACE("Test set/get consistency for " + to_string(volume));
196 auto ret = device->setMasterVolume(volume);
197 ASSERT_TRUE(ret.isOk());
198 ASSERT_EQ(expectedSetResult, ret);
199
200 float observedVolume;
201 ASSERT_OK(device->getMasterVolume(returnIn(res, observedVolume)));
202 ASSERT_OK(res);
203
204 // Check that `get` returned the expected value
205 EXPECT_EQ(expectedGetVolume, observedVolume);
206 }
207};
208
209TEST_F(MasterVolumeTest, MasterVolumeTest) {
210 doc::test("Test the master volume if supported");
211 {
212 SCOPED_TRACE("Check for master volume support");
213 auto ret = device->setMasterVolume(1);
214 ASSERT_TRUE(ret.isOk());
215 if (ret == Result::NOT_SUPPORTED) {
216 doc::partialTest("Master volume is not supported");
217 return;
218 }
219 }
220 // NOTE: this code has never been tested on a platform supporting MasterVolume
221 float lastValidVolumeSet;
222 using Volumes = float[];
223 SCOPED_TRACE("As set/get master volume are supported...");
224 {
225 SCOPED_TRACE("...test them with valid values");
226 for (float validVolume : Volumes{0, 0.5, 1}) {
227 ASSERT_NO_FATAL_FAILURE(testSetGetConsistency(validVolume, Result::OK, validVolume));
228 lastValidVolumeSet = validVolume;
229 }
230 }{
231 SCOPED_TRACE("...test them with tricky values");
232 for (float outOfBoundVolume :Volumes{-0.1, 1.1, NAN, INFINITY, -INFINITY,
233 1 + std::numeric_limits<float>::epsilon()}) {
234 ASSERT_NO_FATAL_FAILURE(testSetGetConsistency(outOfBoundVolume,
235 Result::INVALID_ARGUMENTS,
236 lastValidVolumeSet));
237 }
238 }
239}
240
241//////////////////////////////////////////////////////////////////////////////
242////////////////////////// {set,get}{Master,Mic}Mute /////////////////////////
243//////////////////////////////////////////////////////////////////////////////
244
Kevin Rocard3c405a72017-03-08 16:46:51 -0800245template <class Property>
246class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest {
Kevin Rocardf0357882017-02-10 16:19:28 -0800247protected:
Kevin Rocard3c405a72017-03-08 16:46:51 -0800248
249 /** Test a property getter and setter. */
Kevin Rocardf0357882017-02-10 16:19:28 -0800250 template <class Getter, class Setter>
Kevin Rocard3c405a72017-03-08 16:46:51 -0800251 void testAccessors(const string& propertyName, const vector<Property>& valuesToTest,
252 Setter setter, Getter getter) {
253
254 Property initialValue; // Save initial value to restore it at the end of the test
255 ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
256 ASSERT_OK(res);
257
258 for (Property setValue : valuesToTest) {
259 SCOPED_TRACE("Test " + propertyName + " getter and setter for " + testing::PrintToString(setValue));
260 ASSERT_OK((device.get()->*setter)(setValue));
261 Property getValue;
262 // Make sure the getter returns the same value just set
263 ASSERT_OK((device.get()->*getter)(returnIn(res, getValue)));
Kevin Rocardf0357882017-02-10 16:19:28 -0800264 ASSERT_OK(res);
Kevin Rocard3c405a72017-03-08 16:46:51 -0800265 EXPECT_EQ(setValue, getValue);
Kevin Rocardf0357882017-02-10 16:19:28 -0800266 }
Kevin Rocard3c405a72017-03-08 16:46:51 -0800267
268 ASSERT_OK((device.get()->*setter)(initialValue)); // restore initial value
269 }
270
271 /** Test the getter and setter of an optional feature. */
272 template <class Getter, class Setter>
273 void testOptionalAccessors(const string& propertyName, const vector<Property>& valuesToTest,
274 Setter setter, Getter getter) {
275 doc::test("Test the optional " + propertyName + " getters and setter");
276 {
277 SCOPED_TRACE("Test feature support by calling the getter");
278 Property initialValue;
279 ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
280 if (res == Result::NOT_SUPPORTED) {
281 doc::partialTest(propertyName + " getter is not supported");
282 return;
283 }
284 ASSERT_OK(res); // If it is supported it must succeed
285 }
286 // The feature is supported, test it
287 testAccessors(propertyName, valuesToTest, setter, getter);
Kevin Rocardf0357882017-02-10 16:19:28 -0800288 }
289};
290
Kevin Rocard3c405a72017-03-08 16:46:51 -0800291using BoolAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<bool>;
292
Kevin Rocardf0357882017-02-10 16:19:28 -0800293TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) {
294 doc::test("Check that the mic can be muted and unmuted");
Kevin Rocard3c405a72017-03-08 16:46:51 -0800295 testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute, &IDevice::getMicMute);
Kevin Rocardf0357882017-02-10 16:19:28 -0800296 // TODO: check that the mic is really muted (all sample are 0)
297}
298
299TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) {
300 doc::test("If master mute is supported, try to mute and unmute the master output");
Kevin Rocard3c405a72017-03-08 16:46:51 -0800301 testOptionalAccessors("master mute", {true, false, true},
302 &IDevice::setMasterMute, &IDevice::getMasterMute);
Kevin Rocardf0357882017-02-10 16:19:28 -0800303 // TODO: check that the master volume is really muted
304}
305
306//////////////////////////////////////////////////////////////////////////////
307//////////////// Required and recommended audio format support ///////////////
308// From: https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
309// From: https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
310/////////// TODO: move to the beginning of the file for easier update ////////
311//////////////////////////////////////////////////////////////////////////////
312
313class AudioConfigPrimaryTest : public AudioPrimaryHidlTest {
314public:
315 // Cache result ?
316 static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
317 return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
318 {8000, 11025, 16000, 22050, 32000, 44100},
319 {AudioFormat::PCM_16_BIT});
320 }
321
322 static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
323 return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
324 {24000, 48000},
325 {AudioFormat::PCM_16_BIT});
326 }
327
328 static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
329 // TODO: retrieve audio config supported by the platform
330 // as declared in the policy configuration
331 return {};
332 }
333
334 static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
335 return combineAudioConfig({AudioChannelMask::IN_MONO},
336 {8000, 11025, 16000, 44100},
337 {AudioFormat::PCM_16_BIT});
338 }
339 static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
340 return combineAudioConfig({AudioChannelMask::IN_STEREO},
341 {22050, 48000},
342 {AudioFormat::PCM_16_BIT});
343 }
344 static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
345 // TODO: retrieve audio config supported by the platform
346 // as declared in the policy configuration
347 return {};
348 }
349private:
350 static const vector<AudioConfig> combineAudioConfig(
351 vector<AudioChannelMask> channelMasks,
352 vector<uint32_t> sampleRates,
353 vector<AudioFormat> formats) {
354 vector<AudioConfig> configs;
355 for (auto channelMask: channelMasks) {
356 for (auto sampleRate : sampleRates) {
357 for (auto format : formats) {
358 AudioConfig config{};
359 // leave offloadInfo to 0
360 config.channelMask = channelMask;
361 config.sampleRateHz = sampleRate;
362 config.format = format;
363 // FIXME: leave frameCount to 0 ?
364 configs.push_back(config);
365 }
366 }
367 }
368 return configs;
369 }
370};
371
372//////////////////////////////////////////////////////////////////////////////
373///////////////////////////// getInputBufferSize /////////////////////////////
374//////////////////////////////////////////////////////////////////////////////
375
376// FIXME: execute input test only if platform declares android.hardware.microphone
377// how to get this value ? is it a property ???
378
379class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest,
380 public ::testing::WithParamInterface<AudioConfig> {
381protected:
382 void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
383 uint64_t bufferSize;
384 ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
385
386 switch (res) {
387 case Result::INVALID_ARGUMENTS:
388 EXPECT_FALSE(supportRequired);
389 break;
390 case Result::OK:
391 // Check that the buffer is of a sane size
392 // For now only that it is > 0
393 EXPECT_GT(bufferSize, uint64_t(0));
394 break;
395 default:
396 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
397 }
398 }
399};
400
401// Test that the required capture config and those declared in the policy are indeed supported
402class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
403TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
404 doc::test("Input buffer size must be retrievable for a format with required support.");
405 inputBufferSizeTest(GetParam(), true);
406}
407INSTANTIATE_TEST_CASE_P(
408 RequiredInputBufferSize, RequiredInputBufferSizeTest,
409 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()));
410INSTANTIATE_TEST_CASE_P(
411 SupportedInputBufferSize, RequiredInputBufferSizeTest,
412 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()));
413
414// Test that the recommended capture config are supported or lead to a INVALID_ARGUMENTS return
415class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
416TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
417 doc::test("Input buffer size should be retrievable for a format with recommended support.");
418 inputBufferSizeTest(GetParam(), false);
419}
420INSTANTIATE_TEST_CASE_P(
421 RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
422 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()));
423
424//////////////////////////////////////////////////////////////////////////////
425/////////////////////////////// setScreenState ///////////////////////////////
426//////////////////////////////////////////////////////////////////////////////
427
428TEST_F(AudioPrimaryHidlTest, setScreenState) {
429 doc::test("Check that the hal can receive the screen state");
430 for (bool turnedOn : {false, true, true, false, false}) {
431 auto ret = device->setScreenState(turnedOn);
432 ASSERT_TRUE(ret.isOk());
433 Result result = ret;
434 ASSERT_TRUE(result == Result::OK || result == Result::NOT_SUPPORTED) << toString(result);
435 }
436}
437
438//////////////////////////////////////////////////////////////////////////////
439//////////////////////////// {get,set}Parameters /////////////////////////////
440//////////////////////////////////////////////////////////////////////////////
441
442TEST_F(AudioPrimaryHidlTest, getParameters) {
443 doc::test("Check that the hal can set and get parameters");
444 hidl_vec<hidl_string> keys;
445 hidl_vec<ParameterValue> values;
446 ASSERT_OK(device->getParameters(keys, returnIn(res, values)));
447 ASSERT_OK(device->setParameters(values));
448 values.resize(0);
449 ASSERT_OK(device->setParameters(values));
450}
451
452//////////////////////////////////////////////////////////////////////////////
453//////////////////////////////// debugDebug //////////////////////////////////
454//////////////////////////////////////////////////////////////////////////////
455
456TEST_F(AudioPrimaryHidlTest, debugDump) {
457 doc::test("Check that the hal can dump its state without error");
458 FILE* file = tmpfile();
459 ASSERT_NE(nullptr, file) << errno;
460
461 auto* nativeHandle = native_handle_create(1, 0);
462 ASSERT_NE(nullptr, nativeHandle);
463 nativeHandle->data[0] = fileno(file);
464
465 hidl_handle handle;
466 handle.setTo(nativeHandle, true /*take ownership*/);
467
468 auto ret = device->debugDump(handle);
469 ASSERT_TRUE(ret.isOk());
470
471 // FIXME: debugDump does not return a Result.
472 // This mean that the hal can not report that it not implementing the function.
473 // As the default hal does not implement debugDump, the function can not be tested.
474 /*
475 res = ret;
476 if (res == Result::NOT_SUPPORTED) {
477 doc::partialTest("debugDump is not implemented");
478 return;
479 }
480 ASSERT_OK(res);
481 rewind(file);
482
483 // Check that at least one bit was written by the hal
484 char buff;
485 ASSERT_EQ(1, fread(&buff, sizeof(buff), 1, file));
486 */
487 EXPECT_EQ(0, fclose(file)) << errno;
488}
489
490//////////////////////////////////////////////////////////////////////////////
491////////////////////////// open{Output,Input}Stream //////////////////////////
492//////////////////////////////////////////////////////////////////////////////
493
494template <class Stream>
495class OpenStreamTest : public AudioConfigPrimaryTest,
496 public ::testing::WithParamInterface<AudioConfig> {
497protected:
498 template <class Open>
499 void testOpen(Open openStream, const AudioConfig& config) {
500 // FIXME: Open a stream without an IOHandle
501 // This is not required to be accepted by hal implementations
502 AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
503 AudioConfig suggestedConfig{};
504 ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
505
506 // TODO: only allow failure for RecommendedPlaybackAudioConfig
507 switch (res) {
508 case Result::OK:
509 ASSERT_TRUE(stream != nullptr);
510 audioConfig = config;
511 break;
512 case Result::INVALID_ARGUMENTS:
513 ASSERT_TRUE(stream == nullptr);
514 AudioConfig suggestedConfigRetry;
515 // Could not open stream with config, try again with the suggested one
516 ASSERT_OK(openStream(ioHandle, suggestedConfig,
517 returnIn(res, stream, suggestedConfigRetry)));
518 // This time it must succeed
519 ASSERT_OK(res);
520 ASSERT_TRUE(stream == nullptr);
521 audioConfig = suggestedConfig;
522 break;
523 default:
524 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
525 }
526 open = true;
527 }
528
529private:
530 void TearDown() override {
531 if (open) {
532 ASSERT_OK(stream->close());
533 }
534 }
535
536protected:
537
538 AudioConfig audioConfig;
539 sp<Stream> stream;
540 bool open = false;
541};
542
543////////////////////////////// openOutputStream //////////////////////////////
544
545class OutputStreamTest : public OpenStreamTest<IStreamOut> {
546 virtual void SetUp() override {
547 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
548
549 const AudioConfig& config = GetParam();
550 DeviceAddress deviceAddr{}; // Ignored by primary hal
551 AudioOutputFlag flags = AudioOutputFlag::NONE; // TODO: test all flag combination
552 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
553 { return device->openOutputStream(handle, deviceAddr, config, flags, cb); },
554 config);
555 }
556};
557TEST_P(OutputStreamTest, OpenOutputStreamTest) {
558 doc::test("Check that output streams can be open with the required and recommended config");
559 // Open done in SetUp
560}
561INSTANTIATE_TEST_CASE_P(
562 RequiredOutputStreamConfigSupport, OutputStreamTest,
563 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()));
564INSTANTIATE_TEST_CASE_P(
565 SupportedOutputStreamConfig, OutputStreamTest,
566 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()));
567
568INSTANTIATE_TEST_CASE_P(
569 RecommendedOutputStreamConfigSupport, OutputStreamTest,
570 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()));
571
572////////////////////////////// openInputStream //////////////////////////////
573
574class InputStreamTest : public OpenStreamTest<IStreamIn> {
575
576 virtual void SetUp() override {
577 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
578
579 const AudioConfig& config = GetParam();
580 DeviceAddress deviceAddr{}; // TODO: test all devices
581 AudioInputFlag flags = AudioInputFlag::NONE; // TODO: test all flag combination
582 AudioSource source = AudioSource::DEFAULT; // TODO: test all flag combination
583 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
584 { return device->openInputStream(handle, deviceAddr, config, flags, source, cb); },
585 config);
586 }
587};
588
589TEST_P(InputStreamTest, OpenInputStreamTest) {
590 doc::test("Check that input streams can be open with the required and recommended config");
591 // Open done in setup
592}
593INSTANTIATE_TEST_CASE_P(
594 RequiredInputStreamConfigSupport, InputStreamTest,
595 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()));
596INSTANTIATE_TEST_CASE_P(
597 SupportedInputStreamConfig, InputStreamTest,
598 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()));
599
600INSTANTIATE_TEST_CASE_P(
601 RecommendedInputStreamConfigSupport, InputStreamTest,
602 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()));
603
604//////////////////////////////////////////////////////////////////////////////
605////////////////////////////// IStream getters ///////////////////////////////
606//////////////////////////////////////////////////////////////////////////////
607
608/** Unpack the provided result.
609 * If the result is not OK, register a failure and return an undefined value. */
610template <class R>
611static R extract(Return<R> ret) {
612 if (!ret.isOk()) {
613 ADD_FAILURE();
614 return R{};
615 }
616 return ret;
617}
618
619template <class Property, class CapabilityGetter, class Getter, class Setter>
620static void testCapabilityGetter(const string& name,IStream* stream, Property currentValue,
621 CapabilityGetter capablityGetter, Getter getter, Setter setter) {
622 hidl_vec<Property> capabilities;
623 ASSERT_OK((stream->*capablityGetter)(returnIn(capabilities)));
624 if (capabilities.size() == 0) {
625 // The default hal should probably return a NOT_SUPPORTED if the hal does not expose
626 // capability retrieval. For now it returns an empty list if not implemented
627 doc::partialTest(name + " is not supported");
628 return;
629 };
630 // TODO: This code has never been tested on a hal that supports getSupportedSampleRates
631 EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
632 capabilities.end())
633 << "current " << name << " is not in the list of the supported ones "
634 << toString(capabilities);
635
636 // Check that all declared supported values are indeed supported
637 for (auto capability : capabilities) {
638 ASSERT_OK((stream->*setter)(capability));
639 ASSERT_EQ(capability, extract((stream->*getter)()));
640 }
641}
642
643static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
644 uint32_t sampleRateHz;
645 AudioChannelMask mask;
646 AudioFormat format;
647
648 stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
649
650 // FIXME: the qcom hal it does not currently negotiate the sampleRate & channel mask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800651 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
652 EXPECT_EQ(expectedConfig.channelMask, mask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800653 EXPECT_EQ(expectedConfig.format, format);
654}
655
656static void testAccessors(IStream* stream, AudioConfig audioConfig) {
657 doc::test("Test IStream getters and setters that can be called in the stop state");
658
659 auto frameCount = extract(stream->getFrameCount());
660 ASSERT_EQ(audioConfig.frameCount, frameCount);
661
662 auto sampleRate = extract(stream->getSampleRate());
663 // FIXME: the qcom hal it does not currently negotiate the sampleRate
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800664 ASSERT_EQ(audioConfig.sampleRateHz, sampleRate);
Kevin Rocardf0357882017-02-10 16:19:28 -0800665
666 auto channelMask = extract(stream->getChannelMask());
667 // FIXME: the qcom hal it does not currently negotiate the channelMask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800668 ASSERT_EQ(audioConfig.channelMask, channelMask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800669
670 auto frameSize = extract(stream->getFrameSize());
671 ASSERT_GE(frameSize, 0U);
672
673 auto bufferSize = extract(stream->getBufferSize());
674 ASSERT_GE(bufferSize, frameSize);
675
676 testCapabilityGetter("getSupportedsampleRate", stream, sampleRate,
677 &IStream::getSupportedSampleRates,
678 &IStream::getSampleRate, &IStream::setSampleRate);
679
680 testCapabilityGetter("getSupportedChannelMask", stream, channelMask,
681 &IStream::getSupportedChannelMasks,
682 &IStream::getChannelMask, &IStream::setChannelMask);
683
684 AudioFormat format = extract(stream->getFormat());
685 ASSERT_EQ(audioConfig.format, format);
686
687 testCapabilityGetter("getSupportedFormats", stream, format,
688 &IStream::getSupportedFormats, &IStream::getFormat, &IStream::setFormat);
689
690 testGetAudioProperties(stream, audioConfig);
691
Kevin Rocardfd067c32017-03-08 16:43:29 -0800692 auto ret = stream->getDevice();
693 ASSERT_TRUE(ret.isOk());
694 AudioDevice device = ret;
695 ASSERT_EQ(AudioDevice::OUT_DEFAULT, device);
Kevin Rocardf0357882017-02-10 16:19:28 -0800696}
697
698TEST_P(InputStreamTest, GettersTest) {
699 testAccessors(stream.get(), audioConfig);
700}
701TEST_P(OutputStreamTest, GettersTest) {
702 testAccessors(stream.get(), audioConfig);
703}
704
705//////////////////////////////////////////////////////////////////////////////
706//////////////////////////////// AudioPatches ////////////////////////////////
707//////////////////////////////////////////////////////////////////////////////
708
709
710TEST_F(AudioPrimaryHidlTest, AudioPatches) {
711 doc::test("Test if audio patches are supported");
712 auto result = device->supportsAudioPatches();
713 ASSERT_TRUE(result.isOk());
714 bool supportsAudioPatch = result;
715 if (!supportsAudioPatch) {
716 doc::partialTest("Audio patches are not supported");
717 return;
718 }
719 // TODO: test audio patches
720}
721
722//////////////////////////////////////////////////////////////////////////////
Kevin Rocard3c405a72017-03-08 16:46:51 -0800723/////////////////////////////// PrimaryDevice ////////////////////////////////
724//////////////////////////////////////////////////////////////////////////////
725
726TEST_F(AudioPrimaryHidlTest, setVoiceVolume) {
727 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
728 for (float volume : {0.0, 0.01, 0.5, 0.09, 1.0}) {
729 SCOPED_TRACE("volume=" + to_string(volume));
730 ASSERT_OK(device->setVoiceVolume(volume));
731 }
732 for (float volume : (float[]){-INFINITY,-1.0, -0.0,
733 1.0 + std::numeric_limits<float>::epsilon(), 2.0, INFINITY,
734 NAN}) {
735 SCOPED_TRACE("volume=" + to_string(volume));
736 // FIXME: NAN should never be accepted
737 // FIXME: Missing api doc. What should the impl do if the volume is outside [0,1] ?
738 ASSERT_INVALID_ARGUMENTS(device->setVoiceVolume(volume));
739 }
740}
741
742TEST_F(AudioPrimaryHidlTest, setMode) {
743 doc::test("Make sure setMode always succeeds if mode is valid");
744 for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION,
745 AudioMode::RINGTONE, AudioMode::CURRENT,
746 AudioMode::NORMAL /* Make sure to leave the test in normal mode */ }) {
747 SCOPED_TRACE("mode=" + toString(mode));
748 ASSERT_OK(device->setMode(mode));
749 }
750
751 // FIXME: Missing api doc. What should the impl do if the mode is invalid ?
752 ASSERT_INVALID_ARGUMENTS(device->setMode(AudioMode::INVALID));
753}
754
755
756TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
757 doc::test("Query and set the BT SCO NR&EC state");
758 testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
759 &IPrimaryDevice::setBtScoNrecEnabled,
760 &IPrimaryDevice::getBtScoNrecEnabled);
761}
762
763TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
764 doc::test("Query and set the SCO whideband state");
765 testOptionalAccessors("BtScoWideband", {true, false, true},
766 &IPrimaryDevice::setBtScoWidebandEnabled,
767 &IPrimaryDevice::getBtScoWidebandEnabled);
768}
769
770using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
771TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
772 doc::test("Query and set the TTY mode state");
773 testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
774 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
775}
776
777TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
778 doc::test("Query and set the HAC state");
779 testAccessors("HAC", {true, false, true},
780 &IPrimaryDevice::setHacEnabled,
781 &IPrimaryDevice::getHacEnabled);
782}
783
784//////////////////////////////////////////////////////////////////////////////
Kevin Rocardf0357882017-02-10 16:19:28 -0800785//////////////////// Clean caches on global tear down ////////////////////////
786//////////////////////////////////////////////////////////////////////////////
787
788int main(int argc, char** argv) {
789 environment = new Environment;
790 ::testing::AddGlobalTestEnvironment(environment);
791 ::testing::InitGoogleTest(&argc, argv);
792 int status = RUN_ALL_TESTS();
793 LOG(INFO) << "Test result = " << status;
794 return status;
795}