• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <gtest/gtest.h>
7 
8 extern "C" {
9 #include "cras_audio_format.h"
10 #include "cras_hfp_alsa_iodev.h"
11 #include "cras_hfp_slc.h"
12 #include "cras_iodev.h"
13 }
14 
15 struct hfp_alsa_io {
16   struct cras_iodev base;
17   struct cras_bt_device* device;
18   struct hfp_slc_handle* slc;
19   struct cras_iodev* aio;
20 };
21 
22 static struct cras_iodev fake_sco_out, fake_sco_in;
23 static struct cras_bt_device* fake_device;
24 static struct hfp_slc_handle* fake_slc;
25 
26 static size_t cras_bt_device_append_iodev_called;
27 static size_t cras_bt_device_rm_iodev_called;
28 static size_t cras_iodev_add_node_called;
29 static size_t cras_iodev_rm_node_called;
30 static size_t cras_iodev_set_active_node_called;
31 static size_t cras_iodev_free_format_called;
32 static size_t cras_iodev_free_resources_called;
33 static size_t cras_iodev_set_format_called;
34 static size_t hfp_set_call_status_called;
35 static size_t hfp_event_speaker_gain_called;
36 
37 #define _FAKE_CALL1(name)             \
38   static size_t fake_##name##_called; \
39   static int fake_##name(void* a) {   \
40     fake_##name##_called++;           \
41     return 0;                         \
42   }
43 #define _FAKE_CALL2(name)                    \
44   static size_t fake_##name##_called;        \
45   static int fake_##name(void* a, void* b) { \
46     fake_##name##_called++;                  \
47     return 0;                                \
48   }
49 #define _FAKE_CALL3(name)                             \
50   static size_t fake_##name##_called;                 \
51   static int fake_##name(void* a, void* b, void* c) { \
52     fake_##name##_called++;                           \
53     return 0;                                         \
54   }
55 
56 _FAKE_CALL1(open_dev);
57 _FAKE_CALL1(update_supported_formats);
58 _FAKE_CALL1(configure_dev);
59 _FAKE_CALL1(close_dev);
60 _FAKE_CALL2(frames_queued);
61 _FAKE_CALL1(delay_frames);
62 _FAKE_CALL3(get_buffer);
63 _FAKE_CALL2(put_buffer);
64 _FAKE_CALL1(flush_buffer);
65 _FAKE_CALL3(update_active_node);
66 _FAKE_CALL1(start);
67 _FAKE_CALL2(no_stream);
68 _FAKE_CALL1(is_free_running);
69 
ResetStubData()70 static void ResetStubData() {
71   cras_bt_device_append_iodev_called = 0;
72   cras_bt_device_rm_iodev_called = 0;
73   cras_iodev_add_node_called = 0;
74   cras_iodev_rm_node_called = 0;
75   cras_iodev_set_active_node_called = 0;
76   cras_iodev_free_format_called = 0;
77   cras_iodev_free_resources_called = 0;
78   cras_iodev_set_format_called = 0;
79   hfp_set_call_status_called = 0;
80   hfp_event_speaker_gain_called = 0;
81 
82   fake_sco_out.open_dev = fake_sco_in.open_dev =
83       (int (*)(struct cras_iodev*))fake_open_dev;
84   fake_open_dev_called = 0;
85 
86   fake_sco_out.update_supported_formats = fake_sco_in.update_supported_formats =
87       (int (*)(struct cras_iodev*))fake_update_supported_formats;
88   fake_update_supported_formats_called = 0;
89 
90   fake_sco_out.configure_dev = fake_sco_in.configure_dev =
91       (int (*)(struct cras_iodev*))fake_configure_dev;
92   fake_configure_dev_called = 0;
93 
94   fake_sco_out.close_dev = fake_sco_in.close_dev =
95       (int (*)(struct cras_iodev*))fake_close_dev;
96   fake_close_dev_called = 0;
97 
98   fake_sco_out.frames_queued = fake_sco_in.frames_queued =
99       (int (*)(const struct cras_iodev*, struct timespec*))fake_frames_queued;
100   fake_frames_queued_called = 0;
101 
102   fake_sco_out.delay_frames = fake_sco_in.delay_frames =
103       (int (*)(const struct cras_iodev*))fake_delay_frames;
104   fake_delay_frames_called = 0;
105 
106   fake_sco_out.get_buffer = fake_sco_in.get_buffer = (int (*)(
107       struct cras_iodev*, struct cras_audio_area**, unsigned*))fake_get_buffer;
108   fake_get_buffer_called = 0;
109 
110   fake_sco_out.put_buffer = fake_sco_in.put_buffer =
111       (int (*)(struct cras_iodev*, unsigned))fake_put_buffer;
112   fake_put_buffer_called = 0;
113 
114   fake_sco_out.flush_buffer = fake_sco_in.flush_buffer =
115       (int (*)(struct cras_iodev*))fake_flush_buffer;
116   fake_flush_buffer_called = 0;
117 
118   fake_sco_out.update_active_node = fake_sco_in.update_active_node =
119       (void (*)(struct cras_iodev*, unsigned, unsigned))fake_update_active_node;
120   fake_update_active_node_called = 0;
121 
122   fake_sco_out.start = fake_sco_in.start =
123       (int (*)(const struct cras_iodev*))fake_start;
124   fake_start_called = 0;
125 
126   fake_sco_out.no_stream = fake_sco_in.no_stream =
127       (int (*)(struct cras_iodev*, int))fake_no_stream;
128   fake_no_stream_called = 0;
129 
130   fake_sco_out.is_free_running = fake_sco_in.is_free_running =
131       (int (*)(const struct cras_iodev*))fake_is_free_running;
132   fake_is_free_running_called = 0;
133 }
134 
135 namespace {
136 
137 class HfpAlsaIodev : public testing::Test {
138  protected:
SetUp()139   virtual void SetUp() { ResetStubData(); }
140 
TearDown()141   virtual void TearDown() {}
142 };
143 
TEST_F(HfpAlsaIodev,CreateHfpAlsaOutputIodev)144 TEST_F(HfpAlsaIodev, CreateHfpAlsaOutputIodev) {
145   struct cras_iodev* iodev;
146   struct hfp_alsa_io* hfp_alsa_io;
147 
148   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
149   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
150                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
151   hfp_alsa_io = (struct hfp_alsa_io*)iodev;
152 
153   EXPECT_EQ(CRAS_STREAM_OUTPUT, iodev->direction);
154   EXPECT_EQ(1, cras_bt_device_append_iodev_called);
155   EXPECT_EQ(1, cras_iodev_add_node_called);
156   EXPECT_EQ(1, cras_iodev_set_active_node_called);
157   EXPECT_EQ(&fake_sco_out, hfp_alsa_io->aio);
158 
159   hfp_alsa_iodev_destroy(iodev);
160 
161   EXPECT_EQ(1, cras_bt_device_rm_iodev_called);
162   EXPECT_EQ(1, cras_iodev_rm_node_called);
163   EXPECT_EQ(1, cras_iodev_free_resources_called);
164 }
165 
TEST_F(HfpAlsaIodev,CreateHfpAlsaInputIodev)166 TEST_F(HfpAlsaIodev, CreateHfpAlsaInputIodev) {
167   struct cras_iodev* iodev;
168   struct hfp_alsa_io* hfp_alsa_io;
169 
170   fake_sco_in.direction = CRAS_STREAM_INPUT;
171   iodev = hfp_alsa_iodev_create(&fake_sco_in, fake_device, fake_slc,
172                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
173   hfp_alsa_io = (struct hfp_alsa_io*)iodev;
174 
175   EXPECT_EQ(CRAS_STREAM_INPUT, iodev->direction);
176   EXPECT_EQ(1, cras_bt_device_append_iodev_called);
177   EXPECT_EQ(1, cras_iodev_add_node_called);
178   EXPECT_EQ(1, cras_iodev_set_active_node_called);
179   EXPECT_EQ(&fake_sco_in, hfp_alsa_io->aio);
180   /* Input device does not use software gain. */
181   EXPECT_EQ(0, iodev->software_volume_needed);
182 
183   hfp_alsa_iodev_destroy(iodev);
184 
185   EXPECT_EQ(1, cras_bt_device_rm_iodev_called);
186   EXPECT_EQ(1, cras_iodev_rm_node_called);
187   EXPECT_EQ(1, cras_iodev_free_resources_called);
188 }
189 
TEST_F(HfpAlsaIodev,OpenDev)190 TEST_F(HfpAlsaIodev, OpenDev) {
191   struct cras_iodev* iodev;
192 
193   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
194   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
195                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
196   iodev->open_dev(iodev);
197 
198   EXPECT_EQ(1, fake_open_dev_called);
199 
200   hfp_alsa_iodev_destroy(iodev);
201 }
202 
TEST_F(HfpAlsaIodev,UpdateSupportedFormat)203 TEST_F(HfpAlsaIodev, UpdateSupportedFormat) {
204   struct cras_iodev* iodev;
205   size_t supported_rates[] = {8000, 0};
206   size_t supported_channel_counts[] = {1, 0};
207   snd_pcm_format_t supported_formats[] = {SND_PCM_FORMAT_S16_LE,
208                                           (snd_pcm_format_t)0};
209 
210   fake_sco_out.supported_rates = supported_rates;
211   fake_sco_out.supported_channel_counts = supported_channel_counts;
212   fake_sco_out.supported_formats = supported_formats;
213 
214   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
215   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
216                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
217   iodev->update_supported_formats(iodev);
218 
219   EXPECT_EQ(1, fake_update_supported_formats_called);
220   for (size_t i = 0; i < 2; ++i) {
221     EXPECT_EQ(supported_rates[i], iodev->supported_rates[i]);
222     EXPECT_EQ(supported_channel_counts[i], iodev->supported_channel_counts[i]);
223     EXPECT_EQ(supported_formats[i], iodev->supported_formats[i]);
224   }
225 
226   hfp_alsa_iodev_destroy(iodev);
227 }
228 
TEST_F(HfpAlsaIodev,ConfigureDev)229 TEST_F(HfpAlsaIodev, ConfigureDev) {
230   struct cras_iodev* iodev;
231   size_t buf_size = 8192;
232 
233   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
234   fake_sco_out.buffer_size = buf_size;
235   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
236                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
237   iodev->configure_dev(iodev);
238 
239   EXPECT_EQ(1, fake_configure_dev_called);
240   EXPECT_EQ(1, hfp_set_call_status_called);
241   EXPECT_EQ(buf_size, iodev->buffer_size);
242 
243   hfp_alsa_iodev_destroy(iodev);
244 }
245 
TEST_F(HfpAlsaIodev,CloseDev)246 TEST_F(HfpAlsaIodev, CloseDev) {
247   struct cras_iodev* iodev;
248 
249   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
250   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
251                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
252   iodev->close_dev(iodev);
253 
254   EXPECT_EQ(1, cras_iodev_free_format_called);
255   EXPECT_EQ(1, fake_close_dev_called);
256 
257   hfp_alsa_iodev_destroy(iodev);
258 }
259 
TEST_F(HfpAlsaIodev,FramesQueued)260 TEST_F(HfpAlsaIodev, FramesQueued) {
261   struct cras_iodev* iodev;
262 
263   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
264   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
265                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
266   iodev->frames_queued(iodev, (struct timespec*)NULL);
267 
268   EXPECT_EQ(1, fake_frames_queued_called);
269 
270   hfp_alsa_iodev_destroy(iodev);
271 }
272 
TEST_F(HfpAlsaIodev,DelayFrames)273 TEST_F(HfpAlsaIodev, DelayFrames) {
274   struct cras_iodev* iodev;
275 
276   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
277   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
278                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
279   iodev->delay_frames(iodev);
280 
281   EXPECT_EQ(1, fake_delay_frames_called);
282 
283   hfp_alsa_iodev_destroy(iodev);
284 }
285 
TEST_F(HfpAlsaIodev,GetBuffer)286 TEST_F(HfpAlsaIodev, GetBuffer) {
287   struct cras_iodev* iodev;
288 
289   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
290   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
291                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
292   iodev->get_buffer(iodev, (struct cras_audio_area**)NULL, (unsigned*)NULL);
293 
294   EXPECT_EQ(1, fake_get_buffer_called);
295 
296   hfp_alsa_iodev_destroy(iodev);
297 }
298 
TEST_F(HfpAlsaIodev,PutBuffer)299 TEST_F(HfpAlsaIodev, PutBuffer) {
300   struct cras_iodev* iodev;
301 
302   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
303   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
304                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
305   iodev->put_buffer(iodev, 0xdeadbeef);
306 
307   EXPECT_EQ(1, fake_put_buffer_called);
308 
309   hfp_alsa_iodev_destroy(iodev);
310 }
311 
TEST_F(HfpAlsaIodev,FlushBuffer)312 TEST_F(HfpAlsaIodev, FlushBuffer) {
313   struct cras_iodev* iodev;
314 
315   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
316   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
317                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
318   iodev->flush_buffer(iodev);
319 
320   EXPECT_EQ(1, fake_flush_buffer_called);
321 
322   hfp_alsa_iodev_destroy(iodev);
323 }
324 
TEST_F(HfpAlsaIodev,UpdateActiveNode)325 TEST_F(HfpAlsaIodev, UpdateActiveNode) {
326   struct cras_iodev* iodev;
327 
328   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
329   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
330                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
331   iodev->update_active_node(iodev, 0xdeadbeef, 0xdeadbeef);
332 
333   EXPECT_EQ(1, fake_update_active_node_called);
334 
335   hfp_alsa_iodev_destroy(iodev);
336 }
337 
TEST_F(HfpAlsaIodev,Start)338 TEST_F(HfpAlsaIodev, Start) {
339   struct cras_iodev* iodev;
340 
341   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
342   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
343                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
344   iodev->start(iodev);
345 
346   EXPECT_EQ(1, fake_start_called);
347 
348   hfp_alsa_iodev_destroy(iodev);
349 }
350 
TEST_F(HfpAlsaIodev,SetVolume)351 TEST_F(HfpAlsaIodev, SetVolume) {
352   struct cras_iodev* iodev;
353 
354   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
355   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
356                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
357   iodev->set_volume(iodev);
358 
359   EXPECT_EQ(1, hfp_event_speaker_gain_called);
360 
361   hfp_alsa_iodev_destroy(iodev);
362 }
363 
TEST_F(HfpAlsaIodev,NoStream)364 TEST_F(HfpAlsaIodev, NoStream) {
365   struct cras_iodev* iodev;
366 
367   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
368   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
369                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
370   iodev->min_cb_level = 0xab;
371   iodev->max_cb_level = 0xcd;
372 
373   iodev->no_stream(iodev, 1);
374 
375   EXPECT_EQ(0xab, fake_sco_out.min_cb_level);
376   EXPECT_EQ(0xcd, fake_sco_out.max_cb_level);
377   EXPECT_EQ(1, fake_no_stream_called);
378 
379   hfp_alsa_iodev_destroy(iodev);
380 }
381 
TEST_F(HfpAlsaIodev,IsFreeRunning)382 TEST_F(HfpAlsaIodev, IsFreeRunning) {
383   struct cras_iodev* iodev;
384 
385   fake_sco_out.direction = CRAS_STREAM_OUTPUT;
386   iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc,
387                                 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
388   iodev->is_free_running(iodev);
389 
390   EXPECT_EQ(1, fake_is_free_running_called);
391 
392   hfp_alsa_iodev_destroy(iodev);
393 }
394 
395 }  // namespace
396 
397 extern "C" {
398 
cras_iodev_set_format(struct cras_iodev * iodev,const struct cras_audio_format * fmt)399 int cras_iodev_set_format(struct cras_iodev* iodev,
400                           const struct cras_audio_format* fmt) {
401   cras_iodev_set_format_called++;
402   return 0;
403 }
404 
cras_iodev_free_format(struct cras_iodev * iodev)405 void cras_iodev_free_format(struct cras_iodev* iodev) {
406   cras_iodev_free_format_called++;
407 }
408 
cras_iodev_add_node(struct cras_iodev * iodev,struct cras_ionode * node)409 void cras_iodev_add_node(struct cras_iodev* iodev, struct cras_ionode* node) {
410   cras_iodev_add_node_called++;
411   iodev->nodes = node;
412 }
413 
cras_iodev_rm_node(struct cras_iodev * iodev,struct cras_ionode * node)414 void cras_iodev_rm_node(struct cras_iodev* iodev, struct cras_ionode* node) {
415   cras_iodev_rm_node_called++;
416   iodev->nodes = NULL;
417 }
418 
cras_iodev_set_active_node(struct cras_iodev * iodev,struct cras_ionode * node)419 void cras_iodev_set_active_node(struct cras_iodev* iodev,
420                                 struct cras_ionode* node) {
421   cras_iodev_set_active_node_called++;
422   iodev->active_node = node;
423 }
424 
cras_system_get_volume()425 size_t cras_system_get_volume() {
426   return 0;
427 }
428 
cras_bt_device_name(const struct cras_bt_device * device)429 const char* cras_bt_device_name(const struct cras_bt_device* device) {
430   return "fake-device-name";
431 }
432 
cras_bt_device_address(const struct cras_bt_device * device)433 const char* cras_bt_device_address(const struct cras_bt_device* device) {
434   return "1A:2B:3C:4D:5E:6F";
435 }
436 
cras_bt_device_append_iodev(struct cras_bt_device * device,struct cras_iodev * iodev,enum cras_bt_device_profile profile)437 void cras_bt_device_append_iodev(struct cras_bt_device* device,
438                                  struct cras_iodev* iodev,
439                                  enum cras_bt_device_profile profile) {
440   cras_bt_device_append_iodev_called++;
441 }
442 
cras_bt_device_rm_iodev(struct cras_bt_device * device,struct cras_iodev * iodev)443 void cras_bt_device_rm_iodev(struct cras_bt_device* device,
444                              struct cras_iodev* iodev) {
445   cras_bt_device_rm_iodev_called++;
446 }
447 
cras_bt_device_object_path(const struct cras_bt_device * device)448 const char* cras_bt_device_object_path(const struct cras_bt_device* device) {
449   return "/fake/object/path";
450 }
451 
cras_iodev_free_resources(struct cras_iodev * iodev)452 void cras_iodev_free_resources(struct cras_iodev* iodev) {
453   cras_iodev_free_resources_called++;
454 }
455 
hfp_set_call_status(struct hfp_slc_handle * handle,int call)456 int hfp_set_call_status(struct hfp_slc_handle* handle, int call) {
457   hfp_set_call_status_called++;
458   return 0;
459 }
460 
hfp_event_speaker_gain(struct hfp_slc_handle * handle,int gain)461 int hfp_event_speaker_gain(struct hfp_slc_handle* handle, int gain) {
462   hfp_event_speaker_gain_called++;
463   return 0;
464 }
465 
cras_bt_device_get_sco(struct cras_bt_device * device,int codec)466 int cras_bt_device_get_sco(struct cras_bt_device* device, int codec) {
467   return 0;
468 }
469 
cras_bt_device_put_sco(struct cras_bt_device * device)470 void cras_bt_device_put_sco(struct cras_bt_device* device) {}
471 
hfp_slc_get_selected_codec(struct hfp_slc_handle * handle)472 int hfp_slc_get_selected_codec(struct hfp_slc_handle* handle) {
473   return HFP_CODEC_ID_CVSD;
474 }
475 
476 }  // extern "C"
477 
main(int argc,char ** argv)478 int main(int argc, char** argv) {
479   ::testing::InitGoogleTest(&argc, argv);
480   return RUN_ALL_TESTS();
481 }
482