blob: 1ae169970d741b9f59f651025af6c397006464d7 [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));
Kevin Rocard20e7af62017-03-10 17:10:43 -0800220 EXPECT_RESULT(Result::INVALID_ARGUMENTS, (device.get()->*setter)(invalidValue));
Kevin Rocard92ce35d2017-03-08 17:17:25 -0800221 }
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
Kevin Rocard9c369142017-03-08 17:17:25 -0800338/** Generate a test name based on an audio config.
339 *
340 * As the only parameter changing are channel mask and sample rate,
341 * only print those ones in the test name.
342 */
343static string generateTestName(const testing::TestParamInfo<AudioConfig>& info) {
344 const AudioConfig& config = info.param;
345 return to_string(info.index) + "__" + to_string(config.sampleRateHz)+ "_" +
346 // "MONO" is more clear than "FRONT_LEFT"
347 ((config.channelMask == AudioChannelMask::OUT_MONO ||
348 config.channelMask == AudioChannelMask::IN_MONO) ?
349 "MONO" : toString(config.channelMask));
350}
351
Kevin Rocardf0357882017-02-10 16:19:28 -0800352//////////////////////////////////////////////////////////////////////////////
353///////////////////////////// getInputBufferSize /////////////////////////////
354//////////////////////////////////////////////////////////////////////////////
355
356// FIXME: execute input test only if platform declares android.hardware.microphone
357// how to get this value ? is it a property ???
358
359class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest,
360 public ::testing::WithParamInterface<AudioConfig> {
361protected:
362 void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
363 uint64_t bufferSize;
364 ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize)));
365
366 switch (res) {
367 case Result::INVALID_ARGUMENTS:
368 EXPECT_FALSE(supportRequired);
369 break;
370 case Result::OK:
371 // Check that the buffer is of a sane size
372 // For now only that it is > 0
373 EXPECT_GT(bufferSize, uint64_t(0));
374 break;
375 default:
376 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
377 }
378 }
379};
380
381// Test that the required capture config and those declared in the policy are indeed supported
382class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
383TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
384 doc::test("Input buffer size must be retrievable for a format with required support.");
385 inputBufferSizeTest(GetParam(), true);
386}
387INSTANTIATE_TEST_CASE_P(
388 RequiredInputBufferSize, RequiredInputBufferSizeTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800389 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
390 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800391INSTANTIATE_TEST_CASE_P(
392 SupportedInputBufferSize, RequiredInputBufferSizeTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800393 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
394 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800395
396// Test that the recommended capture config are supported or lead to a INVALID_ARGUMENTS return
397class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
398TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
399 doc::test("Input buffer size should be retrievable for a format with recommended support.");
400 inputBufferSizeTest(GetParam(), false);
401}
402INSTANTIATE_TEST_CASE_P(
403 RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800404 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
405 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800406
407//////////////////////////////////////////////////////////////////////////////
408/////////////////////////////// setScreenState ///////////////////////////////
409//////////////////////////////////////////////////////////////////////////////
410
411TEST_F(AudioPrimaryHidlTest, setScreenState) {
412 doc::test("Check that the hal can receive the screen state");
413 for (bool turnedOn : {false, true, true, false, false}) {
414 auto ret = device->setScreenState(turnedOn);
415 ASSERT_TRUE(ret.isOk());
416 Result result = ret;
417 ASSERT_TRUE(result == Result::OK || result == Result::NOT_SUPPORTED) << toString(result);
418 }
419}
420
421//////////////////////////////////////////////////////////////////////////////
422//////////////////////////// {get,set}Parameters /////////////////////////////
423//////////////////////////////////////////////////////////////////////////////
424
425TEST_F(AudioPrimaryHidlTest, getParameters) {
426 doc::test("Check that the hal can set and get parameters");
427 hidl_vec<hidl_string> keys;
428 hidl_vec<ParameterValue> values;
429 ASSERT_OK(device->getParameters(keys, returnIn(res, values)));
430 ASSERT_OK(device->setParameters(values));
431 values.resize(0);
432 ASSERT_OK(device->setParameters(values));
433}
434
435//////////////////////////////////////////////////////////////////////////////
436//////////////////////////////// debugDebug //////////////////////////////////
437//////////////////////////////////////////////////////////////////////////////
438
Kevin Rocardb9031242017-03-13 12:20:54 -0700439template <class DebugDump>
440static void testDebugDump(DebugDump debugDump) {
Kevin Rocardf0357882017-02-10 16:19:28 -0800441 FILE* file = tmpfile();
442 ASSERT_NE(nullptr, file) << errno;
443
444 auto* nativeHandle = native_handle_create(1, 0);
445 ASSERT_NE(nullptr, nativeHandle);
446 nativeHandle->data[0] = fileno(file);
447
448 hidl_handle handle;
449 handle.setTo(nativeHandle, true /*take ownership*/);
450
Kevin Rocardee771e92017-03-08 17:17:25 -0800451 // TODO: debugDump does not return a Result.
Kevin Rocardf0357882017-02-10 16:19:28 -0800452 // This mean that the hal can not report that it not implementing the function.
Kevin Rocardb9031242017-03-13 12:20:54 -0700453 ASSERT_OK(debugDump(handle));
Kevin Rocardee771e92017-03-08 17:17:25 -0800454
455 rewind(file); // can not fail
Kevin Rocardf0357882017-02-10 16:19:28 -0800456
457 // Check that at least one bit was written by the hal
458 char buff;
Kevin Rocardee771e92017-03-08 17:17:25 -0800459 ASSERT_EQ(size_t{1}, fread(&buff, sizeof(buff), 1, file));
Kevin Rocardf0357882017-02-10 16:19:28 -0800460 EXPECT_EQ(0, fclose(file)) << errno;
461}
462
Kevin Rocardb9031242017-03-13 12:20:54 -0700463TEST_F(AudioPrimaryHidlTest, debugDump) {
464 doc::test("Check that the hal can dump its state without error");
465 testDebugDump([this](const auto& handle){ return device->debugDump(handle); });
466}
467
Kevin Rocardf0357882017-02-10 16:19:28 -0800468//////////////////////////////////////////////////////////////////////////////
469////////////////////////// open{Output,Input}Stream //////////////////////////
470//////////////////////////////////////////////////////////////////////////////
471
472template <class Stream>
473class OpenStreamTest : public AudioConfigPrimaryTest,
474 public ::testing::WithParamInterface<AudioConfig> {
475protected:
476 template <class Open>
477 void testOpen(Open openStream, const AudioConfig& config) {
478 // FIXME: Open a stream without an IOHandle
479 // This is not required to be accepted by hal implementations
480 AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
481 AudioConfig suggestedConfig{};
482 ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
483
484 // TODO: only allow failure for RecommendedPlaybackAudioConfig
485 switch (res) {
486 case Result::OK:
487 ASSERT_TRUE(stream != nullptr);
488 audioConfig = config;
489 break;
490 case Result::INVALID_ARGUMENTS:
491 ASSERT_TRUE(stream == nullptr);
492 AudioConfig suggestedConfigRetry;
493 // Could not open stream with config, try again with the suggested one
494 ASSERT_OK(openStream(ioHandle, suggestedConfig,
495 returnIn(res, stream, suggestedConfigRetry)));
496 // This time it must succeed
497 ASSERT_OK(res);
498 ASSERT_TRUE(stream == nullptr);
499 audioConfig = suggestedConfig;
500 break;
501 default:
502 FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
503 }
504 open = true;
505 }
506
507private:
508 void TearDown() override {
509 if (open) {
510 ASSERT_OK(stream->close());
511 }
512 }
513
514protected:
515
516 AudioConfig audioConfig;
517 sp<Stream> stream;
518 bool open = false;
519};
520
521////////////////////////////// openOutputStream //////////////////////////////
522
523class OutputStreamTest : public OpenStreamTest<IStreamOut> {
524 virtual void SetUp() override {
525 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
526
527 const AudioConfig& config = GetParam();
528 DeviceAddress deviceAddr{}; // Ignored by primary hal
529 AudioOutputFlag flags = AudioOutputFlag::NONE; // TODO: test all flag combination
530 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
531 { return device->openOutputStream(handle, deviceAddr, config, flags, cb); },
532 config);
533 }
534};
535TEST_P(OutputStreamTest, OpenOutputStreamTest) {
536 doc::test("Check that output streams can be open with the required and recommended config");
537 // Open done in SetUp
538}
539INSTANTIATE_TEST_CASE_P(
540 RequiredOutputStreamConfigSupport, OutputStreamTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800541 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()),
542 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800543INSTANTIATE_TEST_CASE_P(
544 SupportedOutputStreamConfig, OutputStreamTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800545 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()),
546 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800547
548INSTANTIATE_TEST_CASE_P(
549 RecommendedOutputStreamConfigSupport, OutputStreamTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800550 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()),
551 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800552
553////////////////////////////// openInputStream //////////////////////////////
554
555class InputStreamTest : public OpenStreamTest<IStreamIn> {
556
557 virtual void SetUp() override {
558 ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
559
560 const AudioConfig& config = GetParam();
561 DeviceAddress deviceAddr{}; // TODO: test all devices
562 AudioInputFlag flags = AudioInputFlag::NONE; // TODO: test all flag combination
563 AudioSource source = AudioSource::DEFAULT; // TODO: test all flag combination
564 testOpen([&](AudioIoHandle handle, AudioConfig config, auto cb)
565 { return device->openInputStream(handle, deviceAddr, config, flags, source, cb); },
566 config);
567 }
568};
569
570TEST_P(InputStreamTest, OpenInputStreamTest) {
571 doc::test("Check that input streams can be open with the required and recommended config");
572 // Open done in setup
573}
574INSTANTIATE_TEST_CASE_P(
575 RequiredInputStreamConfigSupport, InputStreamTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800576 ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()),
577 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800578INSTANTIATE_TEST_CASE_P(
579 SupportedInputStreamConfig, InputStreamTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800580 ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()),
581 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800582
583INSTANTIATE_TEST_CASE_P(
584 RecommendedInputStreamConfigSupport, InputStreamTest,
Kevin Rocard9c369142017-03-08 17:17:25 -0800585 ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()),
586 &generateTestName);
Kevin Rocardf0357882017-02-10 16:19:28 -0800587
588//////////////////////////////////////////////////////////////////////////////
589////////////////////////////// IStream getters ///////////////////////////////
590//////////////////////////////////////////////////////////////////////////////
591
592/** Unpack the provided result.
593 * If the result is not OK, register a failure and return an undefined value. */
594template <class R>
595static R extract(Return<R> ret) {
596 if (!ret.isOk()) {
597 ADD_FAILURE();
598 return R{};
599 }
600 return ret;
601}
602
Kevin Rocarda7df7fc2017-03-10 18:37:46 -0800603/* Could not find a way to write a test for two parametrized class fixure
604 * thus use this macro do duplicate tests for Input and Output stream */
605#define TEST_IO_STREAM(test_name, documentation, code) \
606 TEST_P(InputStreamTest, test_name) { \
607 doc::test(documentation); \
608 code; \
609 } \
610 TEST_P(OutputStreamTest, test_name) { \
611 doc::test(documentation); \
612 code; \
613 }
614
615TEST_IO_STREAM(GetFrameCount, "Check that the stream frame count == the one it was opened with",
616 ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
617
618TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
619 ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
620
621TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it was opened with",
622 ASSERT_EQ(audioConfig.channelMask, extract(stream->getChannelMask())))
623
624TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
625 ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
626
627// TODO: for now only check that the framesize is not incoherent
628TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
629 ASSERT_GT(extract(stream->getFrameSize()), 0U))
630
631TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it was opened with",
632 ASSERT_GE(extract(stream->getBufferSize()), \
633 extract(stream->getFrameSize())));
634
Kevin Rocardf0357882017-02-10 16:19:28 -0800635template <class Property, class CapabilityGetter, class Getter, class Setter>
Kevin Rocarda7df7fc2017-03-10 18:37:46 -0800636static void testCapabilityGetter(const string& name, IStream* stream, Property currentValue,
Kevin Rocardf0357882017-02-10 16:19:28 -0800637 CapabilityGetter capablityGetter, Getter getter, Setter setter) {
638 hidl_vec<Property> capabilities;
639 ASSERT_OK((stream->*capablityGetter)(returnIn(capabilities)));
640 if (capabilities.size() == 0) {
641 // The default hal should probably return a NOT_SUPPORTED if the hal does not expose
642 // capability retrieval. For now it returns an empty list if not implemented
643 doc::partialTest(name + " is not supported");
644 return;
645 };
646 // TODO: This code has never been tested on a hal that supports getSupportedSampleRates
647 EXPECT_NE(std::find(capabilities.begin(), capabilities.end(), currentValue),
648 capabilities.end())
649 << "current " << name << " is not in the list of the supported ones "
650 << toString(capabilities);
651
652 // Check that all declared supported values are indeed supported
653 for (auto capability : capabilities) {
654 ASSERT_OK((stream->*setter)(capability));
655 ASSERT_EQ(capability, extract((stream->*getter)()));
656 }
657}
658
Kevin Rocarda7df7fc2017-03-10 18:37:46 -0800659TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
660 testCapabilityGetter("getSupportedSampleRate", stream.get(), \
661 extract(stream->getSampleRate()), \
662 &IStream::getSupportedSampleRates, \
663 &IStream::getSampleRate, &IStream::setSampleRate))
664
665TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is declared as supported",
666 testCapabilityGetter("getSupportedChannelMask", stream.get(), \
667 extract(stream->getChannelMask()), \
668 &IStream::getSupportedChannelMasks, \
669 &IStream::getChannelMask, &IStream::setChannelMask))
670
671TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
672 testCapabilityGetter("getSupportedFormat", stream.get(), \
673 extract(stream->getFormat()), \
674 &IStream::getSupportedFormats, \
675 &IStream::getFormat, &IStream::setFormat))
676
Kevin Rocardf0357882017-02-10 16:19:28 -0800677static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
678 uint32_t sampleRateHz;
679 AudioChannelMask mask;
680 AudioFormat format;
681
682 stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
683
684 // FIXME: the qcom hal it does not currently negotiate the sampleRate & channel mask
Kevin Rocardd1e98ae2017-03-08 17:17:25 -0800685 EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
686 EXPECT_EQ(expectedConfig.channelMask, mask);
Kevin Rocardf0357882017-02-10 16:19:28 -0800687 EXPECT_EQ(expectedConfig.format, format);
688}
689
Kevin Rocarda7df7fc2017-03-10 18:37:46 -0800690TEST_IO_STREAM(GetAudioProperties,
691 "Check that the stream audio properties == the ones it was opened with",
692 testGetAudioProperties(stream.get(), audioConfig))
Kevin Rocardf0357882017-02-10 16:19:28 -0800693
Kevin Rocardb9031242017-03-13 12:20:54 -0700694TEST_IO_STREAM(DebugDump,
695 "Check that a stream can dump its state without error",
696 testDebugDump([this](const auto& handle){ return stream->debugDump(handle); }))
697
Kevin Rocardf0357882017-02-10 16:19:28 -0800698//////////////////////////////////////////////////////////////////////////////
699//////////////////////////////// AudioPatches ////////////////////////////////
700//////////////////////////////////////////////////////////////////////////////
701
702
703TEST_F(AudioPrimaryHidlTest, AudioPatches) {
704 doc::test("Test if audio patches are supported");
705 auto result = device->supportsAudioPatches();
706 ASSERT_TRUE(result.isOk());
707 bool supportsAudioPatch = result;
708 if (!supportsAudioPatch) {
709 doc::partialTest("Audio patches are not supported");
710 return;
711 }
712 // TODO: test audio patches
713}
714
715//////////////////////////////////////////////////////////////////////////////
Kevin Rocard3c405a72017-03-08 16:46:51 -0800716/////////////////////////////// PrimaryDevice ////////////////////////////////
717//////////////////////////////////////////////////////////////////////////////
718
719TEST_F(AudioPrimaryHidlTest, setVoiceVolume) {
720 doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]");
721 for (float volume : {0.0, 0.01, 0.5, 0.09, 1.0}) {
722 SCOPED_TRACE("volume=" + to_string(volume));
723 ASSERT_OK(device->setVoiceVolume(volume));
724 }
725 for (float volume : (float[]){-INFINITY,-1.0, -0.0,
726 1.0 + std::numeric_limits<float>::epsilon(), 2.0, INFINITY,
727 NAN}) {
728 SCOPED_TRACE("volume=" + to_string(volume));
729 // FIXME: NAN should never be accepted
730 // FIXME: Missing api doc. What should the impl do if the volume is outside [0,1] ?
Kevin Rocard20e7af62017-03-10 17:10:43 -0800731 ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setVoiceVolume(volume));
Kevin Rocard3c405a72017-03-08 16:46:51 -0800732 }
733}
734
735TEST_F(AudioPrimaryHidlTest, setMode) {
736 doc::test("Make sure setMode always succeeds if mode is valid");
737 for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION,
738 AudioMode::RINGTONE, AudioMode::CURRENT,
739 AudioMode::NORMAL /* Make sure to leave the test in normal mode */ }) {
740 SCOPED_TRACE("mode=" + toString(mode));
741 ASSERT_OK(device->setMode(mode));
742 }
743
744 // FIXME: Missing api doc. What should the impl do if the mode is invalid ?
Kevin Rocard20e7af62017-03-10 17:10:43 -0800745 ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(AudioMode::INVALID));
Kevin Rocard3c405a72017-03-08 16:46:51 -0800746}
747
748
749TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) {
750 doc::test("Query and set the BT SCO NR&EC state");
751 testOptionalAccessors("BtScoNrecEnabled", {true, false, true},
752 &IPrimaryDevice::setBtScoNrecEnabled,
753 &IPrimaryDevice::getBtScoNrecEnabled);
754}
755
756TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) {
757 doc::test("Query and set the SCO whideband state");
758 testOptionalAccessors("BtScoWideband", {true, false, true},
759 &IPrimaryDevice::setBtScoWidebandEnabled,
760 &IPrimaryDevice::getBtScoWidebandEnabled);
761}
762
763using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<TtyMode>;
764TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
765 doc::test("Query and set the TTY mode state");
766 testOptionalAccessors("TTY mode", {TtyMode::OFF, TtyMode::HCO, TtyMode::VCO, TtyMode::FULL},
767 &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
768}
769
770TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) {
771 doc::test("Query and set the HAC state");
772 testAccessors("HAC", {true, false, true},
773 &IPrimaryDevice::setHacEnabled,
774 &IPrimaryDevice::getHacEnabled);
775}
776
777//////////////////////////////////////////////////////////////////////////////
Kevin Rocardf0357882017-02-10 16:19:28 -0800778//////////////////// Clean caches on global tear down ////////////////////////
779//////////////////////////////////////////////////////////////////////////////
780
781int main(int argc, char** argv) {
782 environment = new Environment;
783 ::testing::AddGlobalTestEnvironment(environment);
784 ::testing::InitGoogleTest(&argc, argv);
785 int status = RUN_ALL_TESTS();
786 LOG(INFO) << "Test result = " << status;
787 return status;
788}