1 /*
2 * Copyright (C) 2018 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 #include "AudioPrimaryHidlHalTest.h"
18
19 #if MAJOR_VERSION >= 7
20 #include PATH(APM_XSD_H_FILENAME)
21 #include <xsdc/XsdcSupport.h>
22
23 using android::xsdc_enum_range;
24 #endif
25
TEST_P(AudioHidlTest,OpenPrimaryDeviceUsingGetDevice)26 TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
27 doc::test("Calling openDevice(\"primary\") should return the primary device.");
28 if (getDeviceName() != DeviceManager::kPrimaryDevice) {
29 GTEST_SKIP() << "No primary device on this factory"; // returns
30 }
31 EXPECT_TRUE(DeviceManager::getInstance().resetPrimary(getFactoryName()));
32
33 // Must use IDevicesFactory directly because DeviceManager always uses
34 // the latest interfaces version and corresponding methods for opening
35 // them. However, in minor package uprevs IPrimaryDevice does not inherit
36 // IDevice from the same package and thus IDevice can not be upcasted
37 // (see the interfaces in V7.1).
38 auto factory = DevicesFactoryManager::getInstance().get(getFactoryName());
39 ASSERT_TRUE(factory != nullptr);
40 sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IDevice> baseDevice;
41 Result result;
42 auto ret = factory->openDevice(DeviceManager::kPrimaryDevice, returnIn(result, baseDevice));
43 ASSERT_TRUE(ret.isOk()) << ret.description();
44 ASSERT_EQ(Result::OK, result);
45 ASSERT_TRUE(baseDevice != nullptr);
46 {
47 Return<sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice>>
48 primaryDevice = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice::
49 castFrom(baseDevice);
50 EXPECT_TRUE(primaryDevice.isOk());
51 EXPECT_TRUE(sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice>(
52 primaryDevice) != nullptr);
53 }
54 #if MAJOR_VERSION < 6
55 baseDevice.clear();
56 DeviceManager::waitForInstanceDestruction();
57 #else
58 auto closeRet = baseDevice->close();
59 EXPECT_TRUE(closeRet.isOk());
60 #endif
61 }
62
63 //////////////////////////////////////////////////////////////////////////////
64 /////////////////////////// get(Active)Microphones ///////////////////////////
65 //////////////////////////////////////////////////////////////////////////////
66
TEST_P(AudioHidlDeviceTest,GetMicrophonesTest)67 TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) {
68 doc::test("Make sure getMicrophones always succeeds");
69 hidl_vec<MicrophoneInfo> microphones;
70 ASSERT_OK(getDevice()->getMicrophones(returnIn(res, microphones)));
71 if (res == Result::NOT_SUPPORTED) {
72 GTEST_SKIP() << "getMicrophones is not supported"; // returns
73 }
74 ASSERT_OK(res);
75
76 #if MAJOR_VERSION <= 6
77 // In V7, 'getActiveMicrophones' is tested by the 'MicrophoneInfoInputStream'
78 // test which uses the actual configuration of the device.
79
80 if (microphones.size() > 0) {
81 // When there is microphone on the phone, try to open an input stream
82 // and query for the active microphones.
83 doc::test(
84 "Make sure getMicrophones always succeeds"
85 "and getActiveMicrophones always succeeds when recording from these microphones.");
86 AudioConfig config{};
87 config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
88 config.sampleRateHz = 8000;
89 config.format = AudioFormat::PCM_16_BIT;
90 auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
91 const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
92 for (auto microphone : microphones) {
93 if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
94 continue;
95 }
96 sp<IStreamIn> stream;
97 StreamHelper<IStreamIn> helper(stream);
98 AudioConfig suggestedConfig{};
99 ASSERT_NO_FATAL_FAILURE(helper.open(
100 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
101 return getDevice()->openInputStream(handle, microphone.deviceAddress,
102 config, flags, initMetadata, cb);
103 },
104 config, &res, &suggestedConfig));
105 StreamReader reader(stream.get(), stream->getBufferSize());
106 ASSERT_TRUE(reader.start());
107 reader.pause(); // This ensures that at least one read has happened.
108 EXPECT_FALSE(reader.hasError());
109
110 hidl_vec<MicrophoneInfo> activeMicrophones;
111 ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
112 ASSERT_OK(res);
113 EXPECT_NE(0U, activeMicrophones.size());
114 }
115 }
116 #endif // MAJOR_VERSION <= 6
117 }
118
TEST_P(AudioHidlDeviceTest,SetConnectedState)119 TEST_P(AudioHidlDeviceTest, SetConnectedState) {
120 doc::test("Check that the HAL can be notified of device connection and deconnection");
121 #if MAJOR_VERSION <= 6
122 using AD = AudioDevice;
123 for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
124 SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
125 #elif MAJOR_VERSION >= 7
126 using AD = xsd::AudioDevice;
127 for (auto deviceType : {AD::AUDIO_DEVICE_OUT_HDMI, AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
128 AD::AUDIO_DEVICE_IN_USB_HEADSET}) {
129 SCOPED_TRACE("device=" + toString(deviceType));
130 #endif
131 for (bool state : {true, false}) {
132 SCOPED_TRACE("state=" + ::testing::PrintToString(state));
133 DeviceAddress address = {};
134 #if MAJOR_VERSION <= 6
135 address.device = deviceType;
136 #elif MAJOR_VERSION >= 7
137 address.deviceType = toString(deviceType);
138 if (deviceType == AD::AUDIO_DEVICE_IN_USB_HEADSET) {
139 address.address.alsa({0, 0});
140 }
141 #endif
142 auto ret = getDevice()->setConnectedState(address, state);
143 ASSERT_TRUE(ret.isOk());
144 if (ret == Result::NOT_SUPPORTED) {
145 doc::partialTest("setConnectedState is not supported");
146 break; // other deviceType might be supported
147 }
148 ASSERT_OK(ret);
149 }
150 }
151
152 // Because there is no way of knowing if the devices were connected before
153 // calling setConnectedState, there is no way to restore the HAL to its
154 // initial state. To workaround this, destroy the HAL at the end of this test.
155 ASSERT_TRUE(resetDevice());
156 }
157
158 static void testGetDevices(IStream* stream, AudioDevice expectedDevice) {
159 hidl_vec<DeviceAddress> devices;
160 Result res;
161 ASSERT_OK(stream->getDevices(returnIn(res, devices)));
162 if (res == Result::NOT_SUPPORTED) {
163 return doc::partialTest("GetDevices is not supported");
164 }
165 // The stream was constructed with one device, thus getDevices must only return one
166 ASSERT_EQ(1U, devices.size());
167 #if MAJOR_VERSION <= 6
168 AudioDevice device = devices[0].device;
169 #elif MAJOR_VERSION >= 7
170 auto device = devices[0].deviceType;
171 #endif
172 ASSERT_TRUE(device == expectedDevice)
173 << "Expected: " << ::testing::PrintToString(expectedDevice)
174 << "\n Actual: " << ::testing::PrintToString(device);
175 }
176
177 TEST_IO_STREAM(GetDevices, "Check that the stream device == the one it was opened with",
178 areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
179 #if MAJOR_VERSION <= 6
180 : testGetDevices(stream.get(), address.device))
181 #elif MAJOR_VERSION >= 7
182 : testGetDevices(stream.get(), address.deviceType))
183 #endif
184
185 static void testSetDevices(IStream* stream, const DeviceAddress& address) {
186 DeviceAddress otherAddress = address;
187 #if MAJOR_VERSION <= 6
188 otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER
189 : AudioDevice::IN_BUILTIN_MIC;
190 #elif MAJOR_VERSION >= 7
191 otherAddress.deviceType = xsd::isOutputDevice(address.deviceType)
192 ? toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)
193 : toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC);
194 #endif
195 EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress}));
196
197 ASSERT_RESULT(okOrNotSupported,
198 stream->setDevices({address})); // Go back to the original value
199 }
200
201 TEST_IO_STREAM(SetDevices, "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC",
202 areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
203 : testSetDevices(stream.get(), address))
204
205 static void checkGetHwAVSync(::android::hardware::audio::CPP_VERSION::IDevice* device) {
206 Result res;
207 AudioHwSync sync;
208 ASSERT_OK(device->getHwAvSync(returnIn(res, sync)));
209 if (res == Result::NOT_SUPPORTED) {
210 return doc::partialTest("getHwAvSync is not supported");
211 }
212 ASSERT_OK(res);
213 }
214 TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", checkGetHwAVSync(getDevice().get()));
215
216 TEST_P(InputStreamTest, updateSinkMetadata) {
217 doc::test("The HAL should not crash on metadata change");
218 #if MAJOR_VERSION <= 6
219 hidl_enum_range<AudioSource> range;
220 // Test all possible track configuration
221 for (auto source : range) {
222 for (float volume : {0.0, 0.5, 1.0}) {
223 const SinkMetadata metadata = {{{.source = source, .gain = volume}}};
224 ASSERT_OK(stream->updateSinkMetadata(metadata))
225 << "source=" << toString(source) << ", volume=" << volume;
226 }
227 }
228
229 // Do not test concurrent capture as this is not officially supported
230
231 // Set no metadata as if all stream track had stopped
232 ASSERT_OK(stream->updateSinkMetadata({}));
233 // Restore initial
234 ASSERT_OK(stream->updateSinkMetadata(initMetadata));
235
236 #elif MAJOR_VERSION >= 7
237 xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioSource> range;
238 // Test all possible track configuration
239 for (auto source : range) {
240 for (float volume : {0.0, 0.5, 1.0}) {
241 const SinkMetadata metadata = {
242 {{.source = toString(source),
243 .gain = volume,
244 .tags = {},
245 .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
246 ASSERT_RESULT(okOrNotSupported, stream->updateSinkMetadata(metadata))
247 << "source=" << toString(source) << ", volume=" << volume;
248 }
249 }
250 // Do not test concurrent capture as this is not officially supported
251
252 // Set no metadata as if all stream track had stopped
253 ASSERT_RESULT(okOrNotSupported, stream->updateSinkMetadata({}));
254 // Restore initial
255 ASSERT_RESULT(okOrNotSupported, stream->updateSinkMetadata(initMetadata));
256 #endif
257 }
258
259 TEST_P(OutputStreamTest, SelectPresentation) {
260 doc::test("Verify that presentation selection does not crash");
261 ASSERT_RESULT(okOrNotSupported, stream->selectPresentation(0, 0));
262 }
263
264 TEST_P(OutputStreamTest, updateSourceMetadata) {
265 doc::test("The HAL should not crash on metadata change");
266 #if MAJOR_VERSION <= 6
267 hidl_enum_range<AudioUsage> usageRange;
268 hidl_enum_range<AudioContentType> contentRange;
269 // Test all possible track configuration
270 for (auto usage : usageRange) {
271 for (auto content : contentRange) {
272 for (float volume : {0.0, 0.5, 1.0}) {
273 const SourceMetadata metadata = {{{usage, content, volume}}};
274 ASSERT_OK(stream->updateSourceMetadata(metadata))
275 << "usage=" << toString(usage) << ", content=" << toString(content)
276 << ", volume=" << volume;
277 }
278 }
279 }
280 // Set many track of different configuration
281 // clang-format off
282 ASSERT_OK(stream->updateSourceMetadata(
283 {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 0.1},
284 {AudioUsage::VOICE_COMMUNICATION, AudioContentType::SPEECH, 1.0},
285 {AudioUsage::ALARM, AudioContentType::SONIFICATION, 0.0},
286 {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}
287 ));
288 // clang-format on
289 // Set no metadata as if all stream track had stopped
290 ASSERT_OK(stream->updateSourceMetadata({}));
291 // Restore initial
292 ASSERT_OK(stream->updateSourceMetadata(initMetadata));
293 #elif MAJOR_VERSION >= 7
294 xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioUsage> usageRange;
295 xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioContentType>
296 contentRange;
297 // Test all possible track configuration
298 for (auto usage : usageRange) {
299 for (auto content : contentRange) {
300 for (float volume : {0.0, 0.5, 1.0}) {
301 const SourceMetadata metadata = {
302 {{toString(usage),
303 toString(content),
304 volume,
305 toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
306 {} /* tags */}}};
307 ASSERT_RESULT(okOrNotSupported, stream->updateSourceMetadata(metadata))
308 << "usage=" << toString(usage) << ", content=" << toString(content)
309 << ", volume=" << volume;
310 }
311 }
312 }
313 // Set many track of different configuration
314 // clang-format off
315 ASSERT_RESULT(okOrNotSupported, stream->updateSourceMetadata(
316 {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
317 toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
318 0.1, // gain
319 toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
320 {}}, // tags
321 {toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
322 toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH),
323 1.0,
324 toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
325 {}},
326 {toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
327 toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION),
328 0.0,
329 toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
330 {}},
331 {toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
332 toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN),
333 0.3,
334 toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
335 {}}}}
336 ));
337 // clang-format on
338 // Set no metadata as if all stream track had stopped
339 ASSERT_RESULT(okOrNotSupported, stream->updateSourceMetadata({}));
340 // Restore initial
341 ASSERT_RESULT(okOrNotSupported, stream->updateSourceMetadata(initMetadata));
342 #endif
343 }
344
345 TEST_P(AudioPrimaryHidlTest, setMode) {
346 doc::test("Make sure setMode always succeeds if mode is valid and fails otherwise");
347 // Test Invalid values
348 #if MAJOR_VERSION >= 6
349 int maxMode = int(AudioMode::CALL_SCREEN);
350 #else
351 int maxMode = int(AudioMode::IN_COMMUNICATION);
352 #endif
353
354 for (int mode : {-2, -1, maxMode + 1}) {
355 EXPECT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(AudioMode(mode)))
356 << "mode=" << mode;
357 }
358
359 // AudioMode::CALL_SCREEN as support is optional
360 #if MAJOR_VERSION >= 6
361 EXPECT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setMode(AudioMode::CALL_SCREEN));
362 #endif
363 // Test valid values
364 for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE,
365 AudioMode::NORMAL}) {
366 EXPECT_OK(getDevice()->setMode(mode)) << "mode=" << toString(mode);
367 }
368 // Make sure to leave the test in normal mode
369 getDevice()->setMode(AudioMode::NORMAL);
370 }
371
372 TEST_P(AudioPrimaryHidlTest, setBtHfpSampleRate) {
373 doc::test(
374 "Make sure setBtHfpSampleRate either succeeds or "
375 "indicates that it is not supported at all, or that the provided value is invalid");
376 for (auto samplingRate : {8000, 16000, 22050, 24000}) {
377 ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setBtHfpSampleRate(samplingRate));
378 }
379 }
380
381 TEST_P(AudioPrimaryHidlTest, setBtHfpVolume) {
382 doc::test(
383 "Make sure setBtHfpVolume is either not supported or "
384 "only succeed if volume is in [0,1]");
385 auto ret = getDevice()->setBtHfpVolume(0.0);
386 ASSERT_TRUE(ret.isOk());
387 if (ret == Result::NOT_SUPPORTED) {
388 doc::partialTest("setBtHfpVolume is not supported");
389 return;
390 }
391 testUnitaryGain([this](float volume) { return getDevice()->setBtHfpVolume(volume); });
392 }
393
394 TEST_P(AudioPrimaryHidlTest, setBtScoHeadsetDebugName) {
395 doc::test(
396 "Make sure setBtScoHeadsetDebugName either succeeds or "
397 "indicates that it is not supported");
398 ASSERT_RESULT(okOrNotSupported, getDevice()->setBtScoHeadsetDebugName("test"));
399 }
400
401 TEST_P(AudioPrimaryHidlTest, updateRotation) {
402 doc::test("Check that the hal can receive the current rotation");
403 for (Rotation rotation : {Rotation::DEG_0, Rotation::DEG_90, Rotation::DEG_180,
404 Rotation::DEG_270, Rotation::DEG_0}) {
405 ASSERT_RESULT(okOrNotSupported, getDevice()->updateRotation(rotation));
406 }
407 }
408
409 TEST_P(BoolAccessorPrimaryHidlTest, setGetBtHfpEnabled) {
410 doc::test("Query and set the BT HFP state");
411 testAccessors<OPTIONAL>("BtHfpEnabled", Initial{false, OPTIONAL}, {true},
412 &IPrimaryDevice::setBtHfpEnabled, &IPrimaryDevice::getBtHfpEnabled);
413 }
414