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