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