• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2013 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_area.h"
10 #include "cras_hfp_info.h"
11 #include "cras_hfp_iodev.h"
12 #include "cras_hfp_slc.h"
13 #include "cras_iodev.h"
14 }
15 
16 static struct cras_iodev* iodev;
17 static struct cras_bt_device* fake_device;
18 static struct hfp_slc_handle* fake_slc;
19 static struct hfp_info* fake_info;
20 struct cras_audio_format fake_format;
21 static size_t cras_bt_device_append_iodev_called;
22 static size_t cras_bt_device_rm_iodev_called;
23 static size_t cras_iodev_add_node_called;
24 static size_t cras_iodev_rm_node_called;
25 static size_t cras_iodev_set_active_node_called;
26 static size_t cras_iodev_free_format_called;
27 static size_t cras_iodev_free_resources_called;
28 static size_t cras_bt_device_sco_connect_called;
29 static int cras_bt_transport_sco_connect_return_val;
30 static size_t hfp_info_add_iodev_called;
31 static size_t hfp_info_rm_iodev_called;
32 static size_t hfp_info_running_called;
33 static int hfp_info_running_return_val;
34 static size_t hfp_info_has_iodev_called;
35 static int hfp_info_has_iodev_return_val;
36 static size_t hfp_info_start_called;
37 static size_t hfp_info_stop_called;
38 static size_t hfp_buf_acquire_called;
39 static unsigned hfp_buf_acquire_return_val;
40 static size_t hfp_buf_release_called;
41 static unsigned hfp_buf_release_nwritten_val;
42 static size_t hfp_fill_output_with_zeros_called;
43 static size_t hfp_force_output_level_called;
44 static size_t hfp_force_output_level_target;
45 static size_t fake_buffer_size = 500;
46 static cras_audio_area* dummy_audio_area;
47 
ResetStubData()48 void ResetStubData() {
49   cras_bt_device_append_iodev_called = 0;
50   cras_bt_device_rm_iodev_called = 0;
51   cras_iodev_add_node_called = 0;
52   cras_iodev_rm_node_called = 0;
53   cras_iodev_set_active_node_called = 0;
54   cras_iodev_free_format_called = 0;
55   cras_iodev_free_resources_called = 0;
56   cras_bt_device_sco_connect_called = 0;
57   cras_bt_transport_sco_connect_return_val = 0;
58   hfp_info_add_iodev_called = 0;
59   hfp_info_rm_iodev_called = 0;
60   hfp_info_running_called = 0;
61   hfp_info_running_return_val = 1;
62   hfp_info_has_iodev_called = 0;
63   hfp_info_has_iodev_return_val = 0;
64   hfp_info_start_called = 0;
65   hfp_info_stop_called = 0;
66   hfp_buf_acquire_called = 0;
67   hfp_buf_acquire_return_val = 0;
68   hfp_buf_release_called = 0;
69   hfp_buf_release_nwritten_val = 0;
70   hfp_fill_output_with_zeros_called = 0;
71   hfp_force_output_level_called = 0;
72   hfp_force_output_level_target = 0;
73 
74   fake_info = reinterpret_cast<struct hfp_info*>(0x123);
75 
76   if (!dummy_audio_area) {
77     dummy_audio_area = (cras_audio_area*)calloc(
78         1, sizeof(*dummy_audio_area) + sizeof(cras_channel_area) * 2);
79   }
80 }
81 
82 namespace {
83 
84 class HfpIodev : public testing::Test {
85  protected:
SetUp()86   virtual void SetUp() { ResetStubData(); }
87 
TearDown()88   virtual void TearDown() {
89     free(dummy_audio_area);
90     dummy_audio_area = NULL;
91   }
92 };
93 
TEST_F(HfpIodev,CreateHfpOutputIodev)94 TEST_F(HfpIodev, CreateHfpOutputIodev) {
95   iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
96                            CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);
97 
98   ASSERT_EQ(CRAS_STREAM_OUTPUT, iodev->direction);
99   ASSERT_EQ(1, cras_bt_device_append_iodev_called);
100   ASSERT_EQ(1, cras_iodev_add_node_called);
101   ASSERT_EQ(1, cras_iodev_set_active_node_called);
102 
103   hfp_iodev_destroy(iodev);
104 
105   ASSERT_EQ(1, cras_bt_device_rm_iodev_called);
106   ASSERT_EQ(1, cras_iodev_rm_node_called);
107   ASSERT_EQ(1, cras_iodev_free_resources_called);
108 }
109 
TEST_F(HfpIodev,CreateHfpInputIodev)110 TEST_F(HfpIodev, CreateHfpInputIodev) {
111   iodev = hfp_iodev_create(CRAS_STREAM_INPUT, fake_device, fake_slc,
112                            CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);
113 
114   ASSERT_EQ(CRAS_STREAM_INPUT, iodev->direction);
115   ASSERT_EQ(1, cras_bt_device_append_iodev_called);
116   ASSERT_EQ(1, cras_iodev_add_node_called);
117   ASSERT_EQ(1, cras_iodev_set_active_node_called);
118   /* Input device does not use software gain. */
119   ASSERT_EQ(0, iodev->software_volume_needed);
120 
121   hfp_iodev_destroy(iodev);
122 
123   ASSERT_EQ(1, cras_bt_device_rm_iodev_called);
124   ASSERT_EQ(1, cras_iodev_rm_node_called);
125   ASSERT_EQ(1, cras_iodev_free_resources_called);
126 }
127 
TEST_F(HfpIodev,OpenHfpIodev)128 TEST_F(HfpIodev, OpenHfpIodev) {
129   iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
130                            CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);
131   iodev->format = &fake_format;
132 
133   /* hfp_info not start yet */
134   hfp_info_running_return_val = 0;
135   iodev->configure_dev(iodev);
136 
137   ASSERT_EQ(1, cras_bt_device_sco_connect_called);
138   ASSERT_EQ(1, hfp_info_start_called);
139   ASSERT_EQ(1, hfp_info_add_iodev_called);
140 
141   /* hfp_info is running now */
142   hfp_info_running_return_val = 1;
143 
144   iodev->close_dev(iodev);
145   hfp_iodev_destroy(iodev);
146   ASSERT_EQ(1, hfp_info_rm_iodev_called);
147   ASSERT_EQ(1, hfp_info_stop_called);
148   ASSERT_EQ(1, cras_iodev_free_format_called);
149   ASSERT_EQ(1, cras_iodev_free_resources_called);
150 }
151 
TEST_F(HfpIodev,OpenIodevWithHfpInfoAlreadyRunning)152 TEST_F(HfpIodev, OpenIodevWithHfpInfoAlreadyRunning) {
153   iodev = hfp_iodev_create(CRAS_STREAM_INPUT, fake_device, fake_slc,
154                            CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);
155 
156   iodev->format = &fake_format;
157 
158   /* hfp_info already started by another device */
159   hfp_info_running_return_val = 1;
160   iodev->configure_dev(iodev);
161 
162   ASSERT_EQ(0, cras_bt_device_sco_connect_called);
163   ASSERT_EQ(0, hfp_info_start_called);
164   ASSERT_EQ(1, hfp_info_add_iodev_called);
165 
166   hfp_info_has_iodev_return_val = 1;
167   iodev->close_dev(iodev);
168   hfp_iodev_destroy(iodev);
169   ASSERT_EQ(1, hfp_info_rm_iodev_called);
170   ASSERT_EQ(0, hfp_info_stop_called);
171   ASSERT_EQ(1, cras_iodev_free_format_called);
172   ASSERT_EQ(1, cras_iodev_free_resources_called);
173 }
174 
TEST_F(HfpIodev,PutGetBuffer)175 TEST_F(HfpIodev, PutGetBuffer) {
176   cras_audio_area* area;
177   unsigned frames;
178 
179   ResetStubData();
180   iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
181                            CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);
182   iodev->format = &fake_format;
183   iodev->configure_dev(iodev);
184 
185   hfp_buf_acquire_return_val = 100;
186   iodev->get_buffer(iodev, &area, &frames);
187 
188   ASSERT_EQ(1, hfp_buf_acquire_called);
189   ASSERT_EQ(100, frames);
190 
191   iodev->put_buffer(iodev, 40);
192   ASSERT_EQ(1, hfp_buf_release_called);
193   ASSERT_EQ(40, hfp_buf_release_nwritten_val);
194   hfp_iodev_destroy(iodev);
195   ASSERT_EQ(1, cras_iodev_free_resources_called);
196 }
197 
TEST_F(HfpIodev,NoStreamState)198 TEST_F(HfpIodev, NoStreamState) {
199   cras_audio_area* area;
200   unsigned frames;
201 
202   ResetStubData();
203   iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
204                            CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);
205   iodev->format = &fake_format;
206   iodev->configure_dev(iodev);
207   iodev->min_cb_level = iodev->buffer_size / 2;
208 
209   hfp_buf_acquire_return_val = 100;
210   iodev->get_buffer(iodev, &area, &frames);
211   iodev->put_buffer(iodev, 100);
212 
213   iodev->no_stream(iodev, 1);
214   ASSERT_EQ(1, hfp_fill_output_with_zeros_called);
215 
216   iodev->no_stream(iodev, 0);
217   ASSERT_EQ(1, hfp_force_output_level_called);
218   ASSERT_EQ(fake_buffer_size / 2, hfp_force_output_level_target);
219 
220   hfp_iodev_destroy(iodev);
221 }
222 
223 }  // namespace
224 
225 extern "C" {
cras_iodev_free_format(struct cras_iodev * iodev)226 void cras_iodev_free_format(struct cras_iodev* iodev) {
227   cras_iodev_free_format_called++;
228 }
229 
cras_iodev_add_node(struct cras_iodev * iodev,struct cras_ionode * node)230 void cras_iodev_add_node(struct cras_iodev* iodev, struct cras_ionode* node) {
231   cras_iodev_add_node_called++;
232   iodev->nodes = node;
233 }
234 
cras_iodev_rm_node(struct cras_iodev * iodev,struct cras_ionode * node)235 void cras_iodev_rm_node(struct cras_iodev* iodev, struct cras_ionode* node) {
236   cras_iodev_rm_node_called++;
237   iodev->nodes = NULL;
238 }
239 
cras_iodev_set_active_node(struct cras_iodev * iodev,struct cras_ionode * node)240 void cras_iodev_set_active_node(struct cras_iodev* iodev,
241                                 struct cras_ionode* node) {
242   cras_iodev_set_active_node_called++;
243   iodev->active_node = node;
244 }
245 
246 //  From system_state.
cras_system_get_volume()247 size_t cras_system_get_volume() {
248   return 0;
249 }
250 
251 // From bt device
cras_bt_device_sco_connect(struct cras_bt_device * device,int codec)252 int cras_bt_device_sco_connect(struct cras_bt_device* device, int codec) {
253   cras_bt_device_sco_connect_called++;
254   return cras_bt_transport_sco_connect_return_val;
255 }
256 
cras_bt_device_name(const struct cras_bt_device * device)257 const char* cras_bt_device_name(const struct cras_bt_device* device) {
258   return "fake-device-name";
259 }
260 
cras_bt_device_address(const struct cras_bt_device * device)261 const char* cras_bt_device_address(const struct cras_bt_device* device) {
262   return "1A:2B:3C:4D:5E:6F";
263 }
264 
cras_bt_device_append_iodev(struct cras_bt_device * device,struct cras_iodev * iodev,enum cras_bt_device_profile profile)265 void cras_bt_device_append_iodev(struct cras_bt_device* device,
266                                  struct cras_iodev* iodev,
267                                  enum cras_bt_device_profile profile) {
268   cras_bt_device_append_iodev_called++;
269 }
270 
cras_bt_device_rm_iodev(struct cras_bt_device * device,struct cras_iodev * iodev)271 void cras_bt_device_rm_iodev(struct cras_bt_device* device,
272                              struct cras_iodev* iodev) {
273   cras_bt_device_rm_iodev_called++;
274 }
275 
cras_bt_device_sco_packet_size(struct cras_bt_device * device,int sco_socket,int codec)276 int cras_bt_device_sco_packet_size(struct cras_bt_device* device,
277                                    int sco_socket,
278                                    int codec) {
279   return 48;
280 }
cras_bt_device_object_path(const struct cras_bt_device * device)281 const char* cras_bt_device_object_path(const struct cras_bt_device* device) {
282   return "/fake/object/path";
283 }
284 
285 // From cras_hfp_info
hfp_info_add_iodev(struct hfp_info * info,enum CRAS_STREAM_DIRECTION direction,struct cras_audio_format * format)286 int hfp_info_add_iodev(struct hfp_info* info,
287                        enum CRAS_STREAM_DIRECTION direction,
288                        struct cras_audio_format* format) {
289   hfp_info_add_iodev_called++;
290   return 0;
291 }
292 
hfp_info_rm_iodev(struct hfp_info * info,enum CRAS_STREAM_DIRECTION direction)293 int hfp_info_rm_iodev(struct hfp_info* info,
294                       enum CRAS_STREAM_DIRECTION direction) {
295   hfp_info_rm_iodev_called++;
296   return 0;
297 }
298 
hfp_info_has_iodev(struct hfp_info * info)299 int hfp_info_has_iodev(struct hfp_info* info) {
300   hfp_info_has_iodev_called++;
301   return hfp_info_has_iodev_return_val;
302 }
303 
hfp_info_running(struct hfp_info * info)304 int hfp_info_running(struct hfp_info* info) {
305   hfp_info_running_called++;
306   return hfp_info_running_return_val;
307 }
308 
hfp_info_start(int fd,unsigned int mtu,struct hfp_info * info)309 int hfp_info_start(int fd, unsigned int mtu, struct hfp_info* info) {
310   hfp_info_start_called++;
311   return 0;
312 }
313 
hfp_info_stop(struct hfp_info * info)314 int hfp_info_stop(struct hfp_info* info) {
315   hfp_info_stop_called++;
316   return 0;
317 }
318 
hfp_buf_queued(struct hfp_info * info,const enum CRAS_STREAM_DIRECTION direction)319 int hfp_buf_queued(struct hfp_info* info,
320                    const enum CRAS_STREAM_DIRECTION direction) {
321   return 0;
322 }
323 
hfp_buf_size(struct hfp_info * info,enum CRAS_STREAM_DIRECTION direction)324 int hfp_buf_size(struct hfp_info* info, enum CRAS_STREAM_DIRECTION direction) {
325   return fake_buffer_size;
326 }
327 
hfp_buf_acquire(struct hfp_info * info,enum CRAS_STREAM_DIRECTION direction,uint8_t ** buf,unsigned * count)328 void hfp_buf_acquire(struct hfp_info* info,
329                      enum CRAS_STREAM_DIRECTION direction,
330                      uint8_t** buf,
331                      unsigned* count) {
332   hfp_buf_acquire_called++;
333   *count = hfp_buf_acquire_return_val;
334 }
335 
hfp_buf_release(struct hfp_info * info,enum CRAS_STREAM_DIRECTION direction,unsigned written_bytes)336 void hfp_buf_release(struct hfp_info* info,
337                      enum CRAS_STREAM_DIRECTION direction,
338                      unsigned written_bytes) {
339   hfp_buf_release_called++;
340   hfp_buf_release_nwritten_val = written_bytes;
341 }
342 
hfp_fill_output_with_zeros(struct hfp_info * info,unsigned int nframes)343 int hfp_fill_output_with_zeros(struct hfp_info* info, unsigned int nframes) {
344   hfp_fill_output_with_zeros_called++;
345   return 0;
346 }
347 
hfp_force_output_level(struct hfp_info * info,unsigned int level)348 void hfp_force_output_level(struct hfp_info* info, unsigned int level) {
349   hfp_force_output_level_called++;
350   hfp_force_output_level_target = level;
351 }
352 
cras_iodev_init_audio_area(struct cras_iodev * iodev,int num_channels)353 void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) {
354   iodev->area = dummy_audio_area;
355 }
356 
cras_iodev_free_audio_area(struct cras_iodev * iodev)357 void cras_iodev_free_audio_area(struct cras_iodev* iodev) {}
358 
cras_iodev_free_resources(struct cras_iodev * iodev)359 void cras_iodev_free_resources(struct cras_iodev* iodev) {
360   cras_iodev_free_resources_called++;
361 }
362 
cras_audio_area_config_buf_pointers(struct cras_audio_area * area,const struct cras_audio_format * fmt,uint8_t * base_buffer)363 void cras_audio_area_config_buf_pointers(struct cras_audio_area* area,
364                                          const struct cras_audio_format* fmt,
365                                          uint8_t* base_buffer) {
366   dummy_audio_area->channels[0].buf = base_buffer;
367 }
368 
hfp_set_call_status(struct hfp_slc_handle * handle,int call)369 int hfp_set_call_status(struct hfp_slc_handle* handle, int call) {
370   return 0;
371 }
372 
hfp_event_speaker_gain(struct hfp_slc_handle * handle,int gain)373 int hfp_event_speaker_gain(struct hfp_slc_handle* handle, int gain) {
374   return 0;
375 }
376 
hfp_slc_get_selected_codec(struct hfp_slc_handle * handle)377 int hfp_slc_get_selected_codec(struct hfp_slc_handle* handle) {
378   return HFP_CODEC_ID_CVSD;
379 }
380 
381 }  // extern "C"
382 
main(int argc,char ** argv)383 int main(int argc, char** argv) {
384   ::testing::InitGoogleTest(&argc, argv);
385   return RUN_ALL_TESTS();
386 }
387