blob: af2ace5e09d430d12c3df8670b61a90613df521a [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
Yuexi Ma161b5642017-03-10 13:44:22 -080029#include <VtsHalHidlTargetTestBase.h>
Kevin Rocardf0357882017-02-10 16:19:28 -080030
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
Yuexi Ma161b5642017-03-10 13:44:22 -0800116class HidlTest : public ::testing::VtsHalHidlTargetTestBase {
Kevin Rocardf0357882017-02-10 16:19:28 -0800117protected:
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(); });
Yuexi Ma161b5642017-03-10 13:44:22 -0800134 devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService<IDevicesFactory>();
Kevin Rocardf0357882017-02-10 16:19:28 -0800135 }
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
Kevin Rocardee771e92017-03-08 17:17:25 -0800468 // TODO: debugDump does not return a Result.
Kevin Rocardf0357882017-02-10 16:19:28 -0800469 // This mean that the hal can not report that it not implementing the function.
Kevin Rocardee771e92017-03-08 17:17:25 -0800470 ASSERT_OK(device->debugDump(handle));
471
472 rewind(file); // can not fail
Kevin Rocardf0357882017-02-10 16:19:28 -0800473
474 // Check that at least one bit was written by the hal
475 char buff;
Kevin Rocardee771e92017-03-08 17:17:25 -0800476 ASSERT_EQ(size_t{1}, fread(&buff, sizeof(buff), 1, file));
Kevin Rocardf0357882017-02-10 16:19:28 -0800477 EXPECT_EQ(0, fclose(file)) << errno;
478}
479
480//////////////////////////////////////////////////////////////////////////////
481////////////////////////// open{Output,Input}Stream //////////////////////////
482//////////////////////////////////////////////////////////////////////////////
483
484template <class Stream>
485class OpenStreamTest : public AudioConfigPrimaryTest,
486 public ::testing::WithParamInterface<AudioConfig> {
487protected:
488 template <class Open>
489 void testOpen(Open openStream, const AudioConfig& config) {
490 // FIXME: Open a stream without an IOHandle
491 // This is not required to be accepted by hal implementations
492 AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
493 AudioConfig suggestedConfig{};
494 ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
495
496 // TODO: only allow failure for RecommendedPlaybackAudioConfig
497 switch (res) {
498 case Result::OK:
499 ASSERT_TRUE(stream != nullptr);
500 audioConfig = config;
501 break;
502 case Result::INVALID_ARGUMENTS:
503 ASSERT_TRUE(stream == nullptr);
504 AudioConfig suggestedConfigRetry;
505 // Could not open stream with config, try again with the suggested one
506 ASSERT_OK(openStream(ioHandle, suggestedConfig,
507 returnIn(res, stream, suggestedConfigRetry)));
508 // This time it must succeed
509 ASSERT_OK(res);
510 ASSERT_TRUE(stream == nullptr);
511 audioConfig = suggestedConfig;
512 break;
513 default:
514 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
515 }
516 open = true;
517 }
518
519private:
520 void TearDown() override {
521 if (open) {
522 ASSERT_OK(stream->close());
523 }
524 }
525
526protected:
527
528 AudioConfig audioConfig;
529 sp<Stream> stream;
530 bool open = false;
531};
532
533////////////////////////////// openOutputStream //////////////////////////////
534
535class OutputStreamTest : public OpenStreamTest<IStreamOut> {
536 virtual void SetUp() override {
537 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
538
539 const AudioConfig& config = GetParam();
540 DeviceAddress deviceAddr{}; // Ignored by primary hal
541 AudioOutputFlag flags = AudioOutputFlag::NONE; // TODO: test all flag combination
542 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
543 { return device->openOutputStream(handle, deviceAddr, config, flags, cb); },
544 config);
545 }
546};
547TEST_P(OutputStreamTest, OpenOutputStreamTest) {
548 doc::test("Check that output streams can be open with the required and recommended config");
549 // Open done in SetUp
550}
551INSTANTIATE_TEST_CASE_P(
552 RequiredOutputStreamConfigSupport, OutputStreamTest,
553 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()));
554INSTANTIATE_TEST_CASE_P(
555 SupportedOutputStreamConfig, OutputStreamTest,
556 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()));
557
558INSTANTIATE_TEST_CASE_P(
559 RecommendedOutputStreamConfigSupport, OutputStreamTest,
560 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()));
561
562////////////////////////////// openInputStream //////////////////////////////
563
564class InputStreamTest : public OpenStreamTest<IStreamIn> {
565
566 virtual void SetUp() override {
567 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
568
569 const AudioConfig& config = GetParam();
570 DeviceAddress deviceAddr{}; // TODO: test all devices
571 AudioInputFlag flags = AudioInputFlag::NONE; // TODO: test all flag combination
572 AudioSource source = AudioSource::DEFAULT; // TODO: test all flag combination
573 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
574 { return device->openInputStream(handle, deviceAddr, config, flags, source, cb); },
575 config);
576 }
577};
578
579TEST_P(InputStreamTest, OpenInputStreamTest) {
580 doc::test("Check that input streams can be open with the required and recommended config");
581 // Open done in setup
582}
583INSTANTIATE_TEST_CASE_P(
584 RequiredInputStreamConfigSupport, InputStreamTest,
585 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()));
586INSTANTIATE_TEST_CASE_P(
587 SupportedInputStreamConfig, InputStreamTest,
588 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()));
589
590INSTANTIATE_TEST_CASE_P(
591 RecommendedInputStreamConfigSupport, InputStreamTest,
592 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()));
593
594//////////////////////////////////////////////////////////////////////////////
595////////////////////////////// IStream getters ///////////////////////////////
596//////////////////////////////////////////////////////////////////////////////
597
598/** Unpack the provided result.
599 * If the result is not OK, register a failure and return an undefined value. */
600template <class R>
601static R extract(Return<R> ret) {
602 if (!ret.isOk()) {
603 ADD_FAILURE();
604 return R{};
605 }
606 return ret;
607}
608
609template <class Property, class CapabilityGetter, class Getter, class Setter>
610static void testCapabilityGetter(const string& name,IStream* stream, Property currentValue,
611 CapabilityGetter capablityGetter, Getter getter, Setter setter) {
612 hidl_vec<Property> capabilities;
613 ASSERT_OK((stream->*capablityGetter)(returnIn(capabilities)));
614 if (capabilities.size() == 0) {
615 // The default hal should probably return a NOT_SUPPORTED if the hal does not expose
616 // capability retrieval. For now it returns an empty list if not implemented
617 doc::partialTest(name + " is not supported");
618 return;
619 };
620 // TODO: This code has never been tested on a hal that supports getSupportedSampleRates
621 EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
622 capabilities.end())
623 << "current " << name << " is not in the list of the supported ones "
624 << toString(capabilities);
625
626 // Check that all declared supported values are indeed supported
627 for (auto capability : capabilities) {
628 ASSERT_OK((stream->*setter)(capability));
629 ASSERT_EQ(capability, extract((stream->*getter)()));
630 }
631}
632
633static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
634 uint32_t sampleRateHz;
635 AudioChannelMask mask;
636 AudioFormat format;
637
638 stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
639
640 // FIXME: the qcom hal it does not currently negotiate the sampleRate & channel mask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800641 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
642 EXPECT_EQ(expectedConfig.channelMask, mask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800643 EXPECT_EQ(expectedConfig.format, format);
644}
645
646static void testAccessors(IStream* stream, AudioConfig audioConfig) {
647 doc::test("Test IStream getters and setters that can be called in the stop state");
648
649 auto frameCount = extract(stream->getFrameCount());
650 ASSERT_EQ(audioConfig.frameCount, frameCount);
651
652 auto sampleRate = extract(stream->getSampleRate());
653 // FIXME: the qcom hal it does not currently negotiate the sampleRate
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800654 ASSERT_EQ(audioConfig.sampleRateHz, sampleRate);
Kevin Rocardf0357882017-02-10 16:19:28 -0800655
656 auto channelMask = extract(stream->getChannelMask());
657 // FIXME: the qcom hal it does not currently negotiate the channelMask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800658 ASSERT_EQ(audioConfig.channelMask, channelMask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800659
660 auto frameSize = extract(stream->getFrameSize());
661 ASSERT_GE(frameSize, 0U);
662
663 auto bufferSize = extract(stream->getBufferSize());
664 ASSERT_GE(bufferSize, frameSize);
665
666 testCapabilityGetter("getSupportedsampleRate", stream, sampleRate,
667 &IStream::getSupportedSampleRates,
668 &IStream::getSampleRate, &IStream::setSampleRate);
669
670 testCapabilityGetter("getSupportedChannelMask", stream, channelMask,
671 &IStream::getSupportedChannelMasks,
672 &IStream::getChannelMask, &IStream::setChannelMask);
673
674 AudioFormat format = extract(stream->getFormat());
675 ASSERT_EQ(audioConfig.format, format);
676
677 testCapabilityGetter("getSupportedFormats", stream, format,
678 &IStream::getSupportedFormats, &IStream::getFormat, &IStream::setFormat);
679
680 testGetAudioProperties(stream, audioConfig);
681
Kevin Rocardfd067c32017-03-08 16:43:29 -0800682 auto ret = stream->getDevice();
683 ASSERT_TRUE(ret.isOk());
684 AudioDevice device = ret;
685 ASSERT_EQ(AudioDevice::OUT_DEFAULT, device);
Kevin Rocardf0357882017-02-10 16:19:28 -0800686}
687
688TEST_P(InputStreamTest, GettersTest) {
689 testAccessors(stream.get(), audioConfig);
690}
691TEST_P(OutputStreamTest, GettersTest) {
692 testAccessors(stream.get(), audioConfig);
693}
694
695//////////////////////////////////////////////////////////////////////////////
696//////////////////////////////// AudioPatches ////////////////////////////////
697//////////////////////////////////////////////////////////////////////////////
698
699
700TEST_F(AudioPrimaryHidlTest, AudioPatches) {
701 doc::test("Test if audio patches are supported");
702 auto result = device->supportsAudioPatches();
703 ASSERT_TRUE(result.isOk());
704 bool supportsAudioPatch = result;
705 if (!supportsAudioPatch) {
706 doc::partialTest("Audio patches are not supported");
707 return;
708 }
709 // TODO: test audio patches
710}
711
712//////////////////////////////////////////////////////////////////////////////
Kevin Rocard3c405a72017-03-08 16:46:51 -0800713/////////////////////////////// PrimaryDevice ////////////////////////////////
714//////////////////////////////////////////////////////////////////////////////
715
716TEST_F(AudioPrimaryHidlTest, setVoiceVolume) {
717 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
718 for (float volume : {0.0, 0.01, 0.5, 0.09, 1.0}) {
719 SCOPED_TRACE("volume=" + to_string(volume));
720 ASSERT_OK(device->setVoiceVolume(volume));
721 }
722 for (float volume : (float[]){-INFINITY,-1.0, -0.0,
723 1.0 + std::numeric_limits<float>::epsilon(), 2.0, INFINITY,
724 NAN}) {
725 SCOPED_TRACE("volume=" + to_string(volume));
726 // FIXME: NAN should never be accepted
727 // FIXME: Missing api doc. What should the impl do if the volume is outside [0,1] ?
728 ASSERT_INVALID_ARGUMENTS(device->setVoiceVolume(volume));
729 }
730}
731
732TEST_F(AudioPrimaryHidlTest, setMode) {
733 doc::test("Make sure setMode always succeeds if mode is valid");
734 for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION,
735 AudioMode::RINGTONE, AudioMode::CURRENT,
736 AudioMode::NORMAL /* Make sure to leave the test in normal mode */ }) {
737 SCOPED_TRACE("mode=" + toString(mode));
738 ASSERT_OK(device->setMode(mode));
739 }
740
741 // FIXME: Missing api doc. What should the impl do if the mode is invalid ?
742 ASSERT_INVALID_ARGUMENTS(device->setMode(AudioMode::INVALID));
743}
744
745
746TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
747 doc::test("Query and set the BT SCO NR&EC state");
748 testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
749 &IPrimaryDevice::setBtScoNrecEnabled,
750 &IPrimaryDevice::getBtScoNrecEnabled);
751}
752
753TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
754 doc::test("Query and set the SCO whideband state");
755 testOptionalAccessors("BtScoWideband", {true, false, true},
756 &IPrimaryDevice::setBtScoWidebandEnabled,
757 &IPrimaryDevice::getBtScoWidebandEnabled);
758}
759
760using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
761TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
762 doc::test("Query and set the TTY mode state");
763 testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
764 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
765}
766
767TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
768 doc::test("Query and set the HAC state");
769 testAccessors("HAC", {true, false, true},
770 &IPrimaryDevice::setHacEnabled,
771 &IPrimaryDevice::getHacEnabled);
772}
773
774//////////////////////////////////////////////////////////////////////////////
Kevin Rocardf0357882017-02-10 16:19:28 -0800775//////////////////// Clean caches on global tear down ////////////////////////
776//////////////////////////////////////////////////////////////////////////////
777
778int main(int argc, char** argv) {
779 environment = new Environment;
780 ::testing::AddGlobalTestEnvironment(environment);
781 ::testing::InitGoogleTest(&argc, argv);
782 int status = RUN_ALL_TESTS();
783 LOG(INFO) << "Test result = " << status;
784 return status;
785}