• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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