blob: 20a7f228d4efdba94928f511b3f0628fded03a21 [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//////////////////////////////////////////////////////////////////////////////
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800189///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
Kevin Rocardf0357882017-02-10 16:19:28 -0800190//////////////////////////////////////////////////////////////////////////////
191
Kevin Rocard3c405a72017-03-08 16:46:51 -0800192template <class Property>
193class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest {
Kevin Rocardf0357882017-02-10 16:19:28 -0800194protected:
Kevin Rocard3c405a72017-03-08 16:46:51 -0800195
196 /** Test a property getter and setter. */
Kevin Rocardf0357882017-02-10 16:19:28 -0800197 template <class Getter, class Setter>
Kevin Rocard3c405a72017-03-08 16:46:51 -0800198 void testAccessors(const string& propertyName, const vector<Property>& valuesToTest,
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800199 Setter setter, Getter getter,
200 const vector<Property>& invalidValues = {}) {
Kevin Rocard3c405a72017-03-08 16:46:51 -0800201
202 Property initialValue; // Save initial value to restore it at the end of the test
203 ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
204 ASSERT_OK(res);
205
206 for (Property setValue : valuesToTest) {
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800207 SCOPED_TRACE("Test " + propertyName + " getter and setter for " +
208 testing::PrintToString(setValue));
Kevin Rocard3c405a72017-03-08 16:46:51 -0800209 ASSERT_OK((device.get()->*setter)(setValue));
210 Property getValue;
211 // Make sure the getter returns the same value just set
212 ASSERT_OK((device.get()->*getter)(returnIn(res, getValue)));
Kevin Rocardf0357882017-02-10 16:19:28 -0800213 ASSERT_OK(res);
Kevin Rocard3c405a72017-03-08 16:46:51 -0800214 EXPECT_EQ(setValue, getValue);
Kevin Rocardf0357882017-02-10 16:19:28 -0800215 }
Kevin Rocard3c405a72017-03-08 16:46:51 -0800216
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800217 for (Property invalidValue : invalidValues) {
218 SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
219 testing::PrintToString(invalidValue));
220 EXPECT_INVALID_ARGUMENTS((device.get()->*setter)(invalidValue));
221 }
222
Kevin Rocard3c405a72017-03-08 16:46:51 -0800223 ASSERT_OK((device.get()->*setter)(initialValue)); // restore initial value
224 }
225
226 /** Test the getter and setter of an optional feature. */
227 template <class Getter, class Setter>
228 void testOptionalAccessors(const string& propertyName, const vector<Property>& valuesToTest,
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800229 Setter setter, Getter getter,
230 const vector<Property>& invalidValues = {}) {
Kevin Rocard3c405a72017-03-08 16:46:51 -0800231 doc::test("Test the optional " + propertyName + " getters and setter");
232 {
233 SCOPED_TRACE("Test feature support by calling the getter");
234 Property initialValue;
235 ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue)));
236 if (res == Result::NOT_SUPPORTED) {
237 doc::partialTest(propertyName + " getter is not supported");
238 return;
239 }
240 ASSERT_OK(res); // If it is supported it must succeed
241 }
242 // The feature is supported, test it
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800243 testAccessors(propertyName, valuesToTest, setter, getter, invalidValues);
Kevin Rocardf0357882017-02-10 16:19:28 -0800244 }
245};
246
Kevin Rocard3c405a72017-03-08 16:46:51 -0800247using BoolAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<bool>;
248
Kevin Rocardf0357882017-02-10 16:19:28 -0800249TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) {
250 doc::test("Check that the mic can be muted and unmuted");
Kevin Rocard3c405a72017-03-08 16:46:51 -0800251 testAccessors("mic mute", {true, false, true}, &IDevice::setMicMute, &IDevice::getMicMute);
Kevin Rocardf0357882017-02-10 16:19:28 -0800252 // TODO: check that the mic is really muted (all sample are 0)
253}
254
255TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) {
256 doc::test("If master mute is supported, try to mute and unmute the master output");
Kevin Rocard3c405a72017-03-08 16:46:51 -0800257 testOptionalAccessors("master mute", {true, false, true},
258 &IDevice::setMasterMute, &IDevice::getMasterMute);
Kevin Rocardf0357882017-02-10 16:19:28 -0800259 // TODO: check that the master volume is really muted
260}
261
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800262using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<float>;
263TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) {
264 doc::test("Test the master volume if supported");
265 testOptionalAccessors("master volume", {0, 0.5, 1},
266 &IDevice::setMasterVolume, &IDevice::getMasterVolume,
267 {-0.1, 1.1, NAN, INFINITY, -INFINITY,
268 1 + std::numeric_limits<float>::epsilon()});
269 // TODO: check that the master volume is really changed
270}
271
Kevin Rocardf0357882017-02-10 16:19:28 -0800272//////////////////////////////////////////////////////////////////////////////
273//////////////// Required and recommended audio format support ///////////////
274// From: https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
275// From: https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
276/////////// TODO: move to the beginning of the file for easier update ////////
277//////////////////////////////////////////////////////////////////////////////
278
279class AudioConfigPrimaryTest : public AudioPrimaryHidlTest {
280public:
281 // Cache result ?
282 static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
283 return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
284 {8000, 11025, 16000, 22050, 32000, 44100},
285 {AudioFormat::PCM_16_BIT});
286 }
287
288 static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
289 return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
290 {24000, 48000},
291 {AudioFormat::PCM_16_BIT});
292 }
293
294 static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
295 // TODO: retrieve audio config supported by the platform
296 // as declared in the policy configuration
297 return {};
298 }
299
300 static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
301 return combineAudioConfig({AudioChannelMask::IN_MONO},
302 {8000, 11025, 16000, 44100},
303 {AudioFormat::PCM_16_BIT});
304 }
305 static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
306 return combineAudioConfig({AudioChannelMask::IN_STEREO},
307 {22050, 48000},
308 {AudioFormat::PCM_16_BIT});
309 }
310 static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
311 // TODO: retrieve audio config supported by the platform
312 // as declared in the policy configuration
313 return {};
314 }
315private:
316 static const vector<AudioConfig> combineAudioConfig(
317 vector<AudioChannelMask> channelMasks,
318 vector<uint32_t> sampleRates,
319 vector<AudioFormat> formats) {
320 vector<AudioConfig> configs;
321 for (auto channelMask: channelMasks) {
322 for (auto sampleRate : sampleRates) {
323 for (auto format : formats) {
324 AudioConfig config{};
325 // leave offloadInfo to 0
326 config.channelMask = channelMask;
327 config.sampleRateHz = sampleRate;
328 config.format = format;
329 // FIXME: leave frameCount to 0 ?
330 configs.push_back(config);
331 }
332 }
333 }
334 return configs;
335 }
336};
337
338//////////////////////////////////////////////////////////////////////////////
339///////////////////////////// getInputBufferSize /////////////////////////////
340//////////////////////////////////////////////////////////////////////////////
341
342// FIXME: execute input test only if platform declares android.hardware.microphone
343// how to get this value ? is it a property ???
344
345class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest,
346 public ::testing::WithParamInterface<AudioConfig> {
347protected:
348 void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
349 uint64_t bufferSize;
350 ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
351
352 switch (res) {
353 case Result::INVALID_ARGUMENTS:
354 EXPECT_FALSE(supportRequired);
355 break;
356 case Result::OK:
357 // Check that the buffer is of a sane size
358 // For now only that it is > 0
359 EXPECT_GT(bufferSize, uint64_t(0));
360 break;
361 default:
362 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
363 }
364 }
365};
366
367// Test that the required capture config and those declared in the policy are indeed supported
368class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
369TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
370 doc::test("Input buffer size must be retrievable for a format with required support.");
371 inputBufferSizeTest(GetParam(), true);
372}
373INSTANTIATE_TEST_CASE_P(
374 RequiredInputBufferSize, RequiredInputBufferSizeTest,
375 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()));
376INSTANTIATE_TEST_CASE_P(
377 SupportedInputBufferSize, RequiredInputBufferSizeTest,
378 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()));
379
380// Test that the recommended capture config are supported or lead to a INVALID_ARGUMENTS return
381class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
382TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
383 doc::test("Input buffer size should be retrievable for a format with recommended support.");
384 inputBufferSizeTest(GetParam(), false);
385}
386INSTANTIATE_TEST_CASE_P(
387 RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
388 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()));
389
390//////////////////////////////////////////////////////////////////////////////
391/////////////////////////////// setScreenState ///////////////////////////////
392//////////////////////////////////////////////////////////////////////////////
393
394TEST_F(AudioPrimaryHidlTest, setScreenState) {
395 doc::test("Check that the hal can receive the screen state");
396 for (bool turnedOn : {false, true, true, false, false}) {
397 auto ret = device->setScreenState(turnedOn);
398 ASSERT_TRUE(ret.isOk());
399 Result result = ret;
400 ASSERT_TRUE(result == Result::OK || result == Result::NOT_SUPPORTED) << toString(result);
401 }
402}
403
404//////////////////////////////////////////////////////////////////////////////
405//////////////////////////// {get,set}Parameters /////////////////////////////
406//////////////////////////////////////////////////////////////////////////////
407
408TEST_F(AudioPrimaryHidlTest, getParameters) {
409 doc::test("Check that the hal can set and get parameters");
410 hidl_vec<hidl_string> keys;
411 hidl_vec<ParameterValue> values;
412 ASSERT_OK(device->getParameters(keys, returnIn(res, values)));
413 ASSERT_OK(device->setParameters(values));
414 values.resize(0);
415 ASSERT_OK(device->setParameters(values));
416}
417
418//////////////////////////////////////////////////////////////////////////////
419//////////////////////////////// debugDebug //////////////////////////////////
420//////////////////////////////////////////////////////////////////////////////
421
422TEST_F(AudioPrimaryHidlTest, debugDump) {
423 doc::test("Check that the hal can dump its state without error");
424 FILE* file = tmpfile();
425 ASSERT_NE(nullptr, file) << errno;
426
427 auto* nativeHandle = native_handle_create(1, 0);
428 ASSERT_NE(nullptr, nativeHandle);
429 nativeHandle->data[0] = fileno(file);
430
431 hidl_handle handle;
432 handle.setTo(nativeHandle, true /*take ownership*/);
433
Kevin Rocardee771e92017-03-08 17:17:25 -0800434 // TODO: debugDump does not return a Result.
Kevin Rocardf0357882017-02-10 16:19:28 -0800435 // This mean that the hal can not report that it not implementing the function.
Kevin Rocardee771e92017-03-08 17:17:25 -0800436 ASSERT_OK(device->debugDump(handle));
437
438 rewind(file); // can not fail
Kevin Rocardf0357882017-02-10 16:19:28 -0800439
440 // Check that at least one bit was written by the hal
441 char buff;
Kevin Rocardee771e92017-03-08 17:17:25 -0800442 ASSERT_EQ(size_t{1}, fread(&buff, sizeof(buff), 1, file));
Kevin Rocardf0357882017-02-10 16:19:28 -0800443 EXPECT_EQ(0, fclose(file)) << errno;
444}
445
446//////////////////////////////////////////////////////////////////////////////
447////////////////////////// open{Output,Input}Stream //////////////////////////
448//////////////////////////////////////////////////////////////////////////////
449
450template <class Stream>
451class OpenStreamTest : public AudioConfigPrimaryTest,
452 public ::testing::WithParamInterface<AudioConfig> {
453protected:
454 template <class Open>
455 void testOpen(Open openStream, const AudioConfig& config) {
456 // FIXME: Open a stream without an IOHandle
457 // This is not required to be accepted by hal implementations
458 AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
459 AudioConfig suggestedConfig{};
460 ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
461
462 // TODO: only allow failure for RecommendedPlaybackAudioConfig
463 switch (res) {
464 case Result::OK:
465 ASSERT_TRUE(stream != nullptr);
466 audioConfig = config;
467 break;
468 case Result::INVALID_ARGUMENTS:
469 ASSERT_TRUE(stream == nullptr);
470 AudioConfig suggestedConfigRetry;
471 // Could not open stream with config, try again with the suggested one
472 ASSERT_OK(openStream(ioHandle, suggestedConfig,
473 returnIn(res, stream, suggestedConfigRetry)));
474 // This time it must succeed
475 ASSERT_OK(res);
476 ASSERT_TRUE(stream == nullptr);
477 audioConfig = suggestedConfig;
478 break;
479 default:
480 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
481 }
482 open = true;
483 }
484
485private:
486 void TearDown() override {
487 if (open) {
488 ASSERT_OK(stream->close());
489 }
490 }
491
492protected:
493
494 AudioConfig audioConfig;
495 sp<Stream> stream;
496 bool open = false;
497};
498
499////////////////////////////// openOutputStream //////////////////////////////
500
501class OutputStreamTest : public OpenStreamTest<IStreamOut> {
502 virtual void SetUp() override {
503 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
504
505 const AudioConfig& config = GetParam();
506 DeviceAddress deviceAddr{}; // Ignored by primary hal
507 AudioOutputFlag flags = AudioOutputFlag::NONE; // TODO: test all flag combination
508 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
509 { return device->openOutputStream(handle, deviceAddr, config, flags, cb); },
510 config);
511 }
512};
513TEST_P(OutputStreamTest, OpenOutputStreamTest) {
514 doc::test("Check that output streams can be open with the required and recommended config");
515 // Open done in SetUp
516}
517INSTANTIATE_TEST_CASE_P(
518 RequiredOutputStreamConfigSupport, OutputStreamTest,
519 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()));
520INSTANTIATE_TEST_CASE_P(
521 SupportedOutputStreamConfig, OutputStreamTest,
522 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()));
523
524INSTANTIATE_TEST_CASE_P(
525 RecommendedOutputStreamConfigSupport, OutputStreamTest,
526 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()));
527
528////////////////////////////// openInputStream //////////////////////////////
529
530class InputStreamTest : public OpenStreamTest<IStreamIn> {
531
532 virtual void SetUp() override {
533 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
534
535 const AudioConfig& config = GetParam();
536 DeviceAddress deviceAddr{}; // TODO: test all devices
537 AudioInputFlag flags = AudioInputFlag::NONE; // TODO: test all flag combination
538 AudioSource source = AudioSource::DEFAULT; // TODO: test all flag combination
539 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
540 { return device->openInputStream(handle, deviceAddr, config, flags, source, cb); },
541 config);
542 }
543};
544
545TEST_P(InputStreamTest, OpenInputStreamTest) {
546 doc::test("Check that input streams can be open with the required and recommended config");
547 // Open done in setup
548}
549INSTANTIATE_TEST_CASE_P(
550 RequiredInputStreamConfigSupport, InputStreamTest,
551 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()));
552INSTANTIATE_TEST_CASE_P(
553 SupportedInputStreamConfig, InputStreamTest,
554 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()));
555
556INSTANTIATE_TEST_CASE_P(
557 RecommendedInputStreamConfigSupport, InputStreamTest,
558 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()));
559
560//////////////////////////////////////////////////////////////////////////////
561////////////////////////////// IStream getters ///////////////////////////////
562//////////////////////////////////////////////////////////////////////////////
563
564/** Unpack the provided result.
565 * If the result is not OK, register a failure and return an undefined value. */
566template <class R>
567static R extract(Return<R> ret) {
568 if (!ret.isOk()) {
569 ADD_FAILURE();
570 return R{};
571 }
572 return ret;
573}
574
575template <class Property, class CapabilityGetter, class Getter, class Setter>
576static void testCapabilityGetter(const string& name,IStream* stream, Property currentValue,
577 CapabilityGetter capablityGetter, Getter getter, Setter setter) {
578 hidl_vec<Property> capabilities;
579 ASSERT_OK((stream->*capablityGetter)(returnIn(capabilities)));
580 if (capabilities.size() == 0) {
581 // The default hal should probably return a NOT_SUPPORTED if the hal does not expose
582 // capability retrieval. For now it returns an empty list if not implemented
583 doc::partialTest(name + " is not supported");
584 return;
585 };
586 // TODO: This code has never been tested on a hal that supports getSupportedSampleRates
587 EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
588 capabilities.end())
589 << "current " << name << " is not in the list of the supported ones "
590 << toString(capabilities);
591
592 // Check that all declared supported values are indeed supported
593 for (auto capability : capabilities) {
594 ASSERT_OK((stream->*setter)(capability));
595 ASSERT_EQ(capability, extract((stream->*getter)()));
596 }
597}
598
599static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
600 uint32_t sampleRateHz;
601 AudioChannelMask mask;
602 AudioFormat format;
603
604 stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
605
606 // FIXME: the qcom hal it does not currently negotiate the sampleRate & channel mask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800607 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
608 EXPECT_EQ(expectedConfig.channelMask, mask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800609 EXPECT_EQ(expectedConfig.format, format);
610}
611
612static void testAccessors(IStream* stream, AudioConfig audioConfig) {
613 doc::test("Test IStream getters and setters that can be called in the stop state");
614
615 auto frameCount = extract(stream->getFrameCount());
616 ASSERT_EQ(audioConfig.frameCount, frameCount);
617
618 auto sampleRate = extract(stream->getSampleRate());
619 // FIXME: the qcom hal it does not currently negotiate the sampleRate
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800620 ASSERT_EQ(audioConfig.sampleRateHz, sampleRate);
Kevin Rocardf0357882017-02-10 16:19:28 -0800621
622 auto channelMask = extract(stream->getChannelMask());
623 // FIXME: the qcom hal it does not currently negotiate the channelMask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800624 ASSERT_EQ(audioConfig.channelMask, channelMask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800625
626 auto frameSize = extract(stream->getFrameSize());
627 ASSERT_GE(frameSize, 0U);
628
629 auto bufferSize = extract(stream->getBufferSize());
630 ASSERT_GE(bufferSize, frameSize);
631
632 testCapabilityGetter("getSupportedsampleRate", stream, sampleRate,
633 &IStream::getSupportedSampleRates,
634 &IStream::getSampleRate, &IStream::setSampleRate);
635
636 testCapabilityGetter("getSupportedChannelMask", stream, channelMask,
637 &IStream::getSupportedChannelMasks,
638 &IStream::getChannelMask, &IStream::setChannelMask);
639
640 AudioFormat format = extract(stream->getFormat());
641 ASSERT_EQ(audioConfig.format, format);
642
643 testCapabilityGetter("getSupportedFormats", stream, format,
644 &IStream::getSupportedFormats, &IStream::getFormat, &IStream::setFormat);
645
646 testGetAudioProperties(stream, audioConfig);
647
Kevin Rocardfd067c32017-03-08 16:43:29 -0800648 auto ret = stream->getDevice();
649 ASSERT_TRUE(ret.isOk());
650 AudioDevice device = ret;
651 ASSERT_EQ(AudioDevice::OUT_DEFAULT, device);
Kevin Rocardf0357882017-02-10 16:19:28 -0800652}
653
654TEST_P(InputStreamTest, GettersTest) {
655 testAccessors(stream.get(), audioConfig);
656}
657TEST_P(OutputStreamTest, GettersTest) {
658 testAccessors(stream.get(), audioConfig);
659}
660
661//////////////////////////////////////////////////////////////////////////////
662//////////////////////////////// AudioPatches ////////////////////////////////
663//////////////////////////////////////////////////////////////////////////////
664
665
666TEST_F(AudioPrimaryHidlTest, AudioPatches) {
667 doc::test("Test if audio patches are supported");
668 auto result = device->supportsAudioPatches();
669 ASSERT_TRUE(result.isOk());
670 bool supportsAudioPatch = result;
671 if (!supportsAudioPatch) {
672 doc::partialTest("Audio patches are not supported");
673 return;
674 }
675 // TODO: test audio patches
676}
677
678//////////////////////////////////////////////////////////////////////////////
Kevin Rocard3c405a72017-03-08 16:46:51 -0800679/////////////////////////////// PrimaryDevice ////////////////////////////////
680//////////////////////////////////////////////////////////////////////////////
681
682TEST_F(AudioPrimaryHidlTest, setVoiceVolume) {
683 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
684 for (float volume : {0.0, 0.01, 0.5, 0.09, 1.0}) {
685 SCOPED_TRACE("volume=" + to_string(volume));
686 ASSERT_OK(device->setVoiceVolume(volume));
687 }
688 for (float volume : (float[]){-INFINITY,-1.0, -0.0,
689 1.0 + std::numeric_limits<float>::epsilon(), 2.0, INFINITY,
690 NAN}) {
691 SCOPED_TRACE("volume=" + to_string(volume));
692 // FIXME: NAN should never be accepted
693 // FIXME: Missing api doc. What should the impl do if the volume is outside [0,1] ?
694 ASSERT_INVALID_ARGUMENTS(device->setVoiceVolume(volume));
695 }
696}
697
698TEST_F(AudioPrimaryHidlTest, setMode) {
699 doc::test("Make sure setMode always succeeds if mode is valid");
700 for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION,
701 AudioMode::RINGTONE, AudioMode::CURRENT,
702 AudioMode::NORMAL /* Make sure to leave the test in normal mode */ }) {
703 SCOPED_TRACE("mode=" + toString(mode));
704 ASSERT_OK(device->setMode(mode));
705 }
706
707 // FIXME: Missing api doc. What should the impl do if the mode is invalid ?
708 ASSERT_INVALID_ARGUMENTS(device->setMode(AudioMode::INVALID));
709}
710
711
712TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
713 doc::test("Query and set the BT SCO NR&EC state");
714 testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
715 &IPrimaryDevice::setBtScoNrecEnabled,
716 &IPrimaryDevice::getBtScoNrecEnabled);
717}
718
719TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
720 doc::test("Query and set the SCO whideband state");
721 testOptionalAccessors("BtScoWideband", {true, false, true},
722 &IPrimaryDevice::setBtScoWidebandEnabled,
723 &IPrimaryDevice::getBtScoWidebandEnabled);
724}
725
726using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
727TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
728 doc::test("Query and set the TTY mode state");
729 testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
730 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
731}
732
733TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
734 doc::test("Query and set the HAC state");
735 testAccessors("HAC", {true, false, true},
736 &IPrimaryDevice::setHacEnabled,
737 &IPrimaryDevice::getHacEnabled);
738}
739
740//////////////////////////////////////////////////////////////////////////////
Kevin Rocardf0357882017-02-10 16:19:28 -0800741//////////////////// Clean caches on global tear down ////////////////////////
742//////////////////////////////////////////////////////////////////////////////
743
744int main(int argc, char** argv) {
745 environment = new Environment;
746 ::testing::AddGlobalTestEnvironment(environment);
747 ::testing::InitGoogleTest(&argc, argv);
748 int status = RUN_ALL_TESTS();
749 LOG(INFO) << "Test result = " << status;
750 return status;
751}