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 #include <stdint.h>
8 #include <stdio.h>
9 #include <sys/socket.h>
10
11 extern "C" {
12 #include "cras_bt_log.h"
13 #include "cras_hfp_slc.h"
14 #include "cras_telephony.h"
15 }
16
17 static struct hfp_slc_handle* handle;
18 static struct cras_telephony_handle fake_telephony;
19 static int cras_bt_device_update_hardware_volume_called;
20 static int cras_observer_notify_bt_batter_changed_called;
21 static int slc_initialized_cb_called;
22 static int slc_disconnected_cb_called;
23 static int cras_system_add_select_fd_called;
24 static void (*slc_cb)(void* data);
25 static void* slc_cb_data;
26 static int fake_errno;
27 static struct cras_bt_device* device =
28 reinterpret_cast<struct cras_bt_device*>(2);
29 static void (*cras_tm_timer_cb)(struct cras_timer* t, void* data);
30 static void* cras_tm_timer_cb_data;
31
32 int slc_initialized_cb(struct hfp_slc_handle* handle);
33 int slc_disconnected_cb(struct hfp_slc_handle* handle);
34
ResetStubData()35 void ResetStubData() {
36 slc_initialized_cb_called = 0;
37 cras_system_add_select_fd_called = 0;
38 cras_bt_device_update_hardware_volume_called = 0;
39 cras_observer_notify_bt_batter_changed_called = 0;
40 slc_cb = NULL;
41 slc_cb_data = NULL;
42 }
43
44 namespace {
45
TEST(HfpSlc,CreateSlcHandle)46 TEST(HfpSlc, CreateSlcHandle) {
47 ResetStubData();
48
49 handle = hfp_slc_create(0, 0, AG_ENHANCED_CALL_STATUS, device,
50 slc_initialized_cb, slc_disconnected_cb);
51 ASSERT_EQ(1, cras_system_add_select_fd_called);
52 ASSERT_EQ(handle, slc_cb_data);
53
54 hfp_slc_destroy(handle);
55 }
56
TEST(HfpSlc,InitializeSlc)57 TEST(HfpSlc, InitializeSlc) {
58 int err;
59 int sock[2];
60 char buf[256];
61 char* chp;
62 ResetStubData();
63
64 btlog = cras_bt_event_log_init();
65
66 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
67 handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device,
68 slc_initialized_cb, slc_disconnected_cb);
69
70 err = write(sock[1], "AT+CIND=?\r", 10);
71 ASSERT_EQ(10, err);
72 slc_cb(slc_cb_data);
73 err = read(sock[1], buf, 256);
74
75 /* Assert "\r\n+CIND: ... \r\n" response is received */
76 chp = strstr(buf, "\r\n");
77 ASSERT_NE((void*)NULL, (void*)chp);
78 ASSERT_EQ(0, strncmp("\r\n+CIND:", chp, 8));
79 chp += 2;
80 chp = strstr(chp, "\r\n");
81 ASSERT_NE((void*)NULL, (void*)chp);
82
83 /* Assert "\r\nOK\r\n" response is received */
84 chp += 2;
85 chp = strstr(chp, "\r\n");
86 ASSERT_NE((void*)NULL, (void*)chp);
87 ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
88
89 err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
90 ASSERT_EQ(16, err);
91 slc_cb(slc_cb_data);
92
93 ASSERT_EQ(1, slc_initialized_cb_called);
94
95 /* Assert "\r\nOK\r\n" response is received */
96 err = read(sock[1], buf, 256);
97
98 chp = strstr(buf, "\r\n");
99 ASSERT_NE((void*)NULL, (void*)chp);
100 ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
101
102 err = write(sock[1], "AT+VGS=13\r", 10);
103 ASSERT_EQ(err, 10);
104 slc_cb(slc_cb_data);
105
106 err = read(sock[1], buf, 256);
107
108 chp = strstr(buf, "\r\n");
109 ASSERT_NE((void*)NULL, (void*)chp);
110 ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
111
112 ASSERT_EQ(1, cras_bt_device_update_hardware_volume_called);
113
114 hfp_slc_destroy(handle);
115 cras_bt_event_log_deinit(btlog);
116 }
117
TEST(HfpSlc,DisconnectSlc)118 TEST(HfpSlc, DisconnectSlc) {
119 int sock[2];
120 ResetStubData();
121
122 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
123 handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device,
124 slc_initialized_cb, slc_disconnected_cb);
125 /* Close socket right away to make read() get negative err code, and
126 * fake the errno to ECONNRESET. */
127 close(sock[0]);
128 close(sock[1]);
129 fake_errno = 104;
130 slc_cb(slc_cb_data);
131
132 ASSERT_EQ(1, slc_disconnected_cb_called);
133
134 hfp_slc_destroy(handle);
135 }
136
TEST(HfpSlc,InitializeSlcSupportsHfIndicator)137 TEST(HfpSlc, InitializeSlcSupportsHfIndicator) {
138 int err;
139 int sock[2];
140 char buf[256];
141 char* chp;
142 ResetStubData();
143
144 btlog = cras_bt_event_log_init();
145
146 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
147 handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device,
148 slc_initialized_cb, slc_disconnected_cb);
149
150 /* Fake that HF supports HF indicator. */
151 err = write(sock[1], "AT+BRSF=256\r", 12);
152 ASSERT_EQ(err, 12);
153 slc_cb(slc_cb_data);
154 err = read(sock[1], buf, 256);
155
156 err = write(sock[1], "AT+CIND=?\r", 10);
157 ASSERT_EQ(10, err);
158 slc_cb(slc_cb_data);
159 err = read(sock[1], buf, 256);
160
161 /* Assert "\r\n+CIND: ... \r\n" response is received */
162 chp = strstr(buf, "\r\n");
163 ASSERT_NE((void*)NULL, (void*)chp);
164 ASSERT_EQ(0, strncmp("\r\n+CIND:", chp, 8));
165 chp += 2;
166 chp = strstr(chp, "\r\n");
167 ASSERT_NE((void*)NULL, (void*)chp);
168
169 /* Assert "\r\nOK\r\n" response is received */
170 chp += 2;
171 chp = strstr(chp, "\r\n");
172 ASSERT_NE((void*)NULL, (void*)chp);
173 ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
174
175 err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
176 ASSERT_EQ(16, err);
177 slc_cb(slc_cb_data);
178
179 ASSERT_NE((void*)NULL, cras_tm_timer_cb);
180 ASSERT_EQ(0, slc_initialized_cb_called);
181
182 /* Assert "\r\nOK\r\n" response is received */
183 err = read(sock[1], buf, 256);
184
185 chp = strstr(buf, "\r\nOK\r\n");
186 ASSERT_NE((void*)NULL, (void*)chp);
187
188 err = write(sock[1], "AT+BIND=2\r", 10);
189 ASSERT_EQ(err, 10);
190 slc_cb(slc_cb_data);
191
192 /* Assert "\r\nOK\r\n" response is received */
193 err = read(sock[1], buf, 256);
194
195 chp = strstr(buf, "\r\nOK\r\n");
196 ASSERT_NE((void*)NULL, (void*)chp);
197
198 err = write(sock[1], "AT+BIND=?\r", 10);
199 ASSERT_EQ(err, 10);
200 slc_cb(slc_cb_data);
201
202 /* Assert "\r\n+BIND: (2)\r\n" response is received */
203 err = read(sock[1], buf, 256);
204
205 chp = strstr(buf, "\r\n+BIND: (1,2)\r\n");
206 ASSERT_NE((void*)NULL, (void*)chp);
207 chp = strstr(buf, "\r\nOK\r\n");
208 ASSERT_NE((void*)NULL, (void*)chp);
209
210 err = write(sock[1], "AT+BIND?\r", 9);
211 ASSERT_EQ(err, 9);
212 slc_cb(slc_cb_data);
213
214 /* Assert "\r\n+BIND: 2,1\r\n" response is received */
215 err = read(sock[1], buf, 256);
216
217 chp = strstr(buf, "\r\n+BIND: 2,1\r\n");
218 ASSERT_NE((void*)NULL, (void*)chp);
219 chp = strstr(buf, "\r\nOK\r\n");
220 ASSERT_NE((void*)NULL, (void*)chp);
221
222 ASSERT_EQ(1, slc_initialized_cb_called);
223
224 err = write(sock[1], "AT+VGS=13\r", 10);
225 ASSERT_EQ(err, 10);
226 slc_cb(slc_cb_data);
227
228 err = read(sock[1], buf, 256);
229
230 chp = strstr(buf, "\r\nOK\r\n");
231 ASSERT_NE((void*)NULL, (void*)chp);
232
233 ASSERT_EQ(1, cras_bt_device_update_hardware_volume_called);
234
235 hfp_slc_destroy(handle);
236 cras_bt_event_log_deinit(btlog);
237 }
238
TEST(HfpSlc,CodecNegotiation)239 TEST(HfpSlc, CodecNegotiation) {
240 int codec;
241 int err;
242 int sock[2];
243 char buf[256];
244 char* pos;
245 ResetStubData();
246
247 btlog = cras_bt_event_log_init();
248
249 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
250 handle = hfp_slc_create(sock[0], 0, AG_CODEC_NEGOTIATION, device,
251 slc_initialized_cb, slc_disconnected_cb);
252
253 codec = hfp_slc_get_selected_codec(handle);
254 EXPECT_EQ(HFP_CODEC_ID_CVSD, codec);
255
256 /* Fake that HF supports codec negotiation. */
257 err = write(sock[1], "AT+BRSF=128\r", 12);
258 ASSERT_EQ(err, 12);
259 slc_cb(slc_cb_data);
260 err = read(sock[1], buf, 256);
261
262 /* Fake that HF supports mSBC codec. */
263 err = write(sock[1], "AT+BAC=1,2\r", 11);
264 ASSERT_EQ(err, 11);
265 slc_cb(slc_cb_data);
266 err = read(sock[1], buf, 256);
267
268 /* Fake event reporting command to indicate SLC established. */
269 err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
270 ASSERT_EQ(err, 16);
271 slc_cb(slc_cb_data);
272
273 /* Assert that AG side prefers mSBC codec. */
274 codec = hfp_slc_get_selected_codec(handle);
275 EXPECT_EQ(HFP_CODEC_ID_MSBC, codec);
276
277 /* Fake HF selects mSBC codec. */
278 err = write(sock[1], "AT+BCS=2\r", 9);
279 ASSERT_EQ(err, 9);
280
281 err = hfp_slc_codec_connection_setup(handle);
282 /* Assert CRAS initiates codec selection to mSBC. */
283 memset(buf, 0, 256);
284 err = read(sock[1], buf, 256);
285 pos = strstr(buf, "\r\n+BCS:2\r\n");
286 ASSERT_NE((void*)NULL, pos);
287
288 err = write(sock[1], "AT+VGS=9\r", 9);
289 ASSERT_EQ(err, 9);
290 slc_cb(slc_cb_data);
291
292 hfp_slc_destroy(handle);
293 cras_bt_event_log_deinit(btlog);
294 }
295
TEST(HfpSlc,CodecNegotiationCapabilityChanged)296 TEST(HfpSlc, CodecNegotiationCapabilityChanged) {
297 int codec;
298 int err;
299 int sock[2];
300 char buf[256];
301 char* pos;
302 ResetStubData();
303
304 btlog = cras_bt_event_log_init();
305
306 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
307 handle = hfp_slc_create(sock[0], 0, AG_CODEC_NEGOTIATION, device,
308 slc_initialized_cb, slc_disconnected_cb);
309
310 codec = hfp_slc_get_selected_codec(handle);
311 EXPECT_EQ(HFP_CODEC_ID_CVSD, codec);
312
313 /* Fake that HF supports codec negotiation. */
314 err = write(sock[1], "AT+BRSF=128\r", 12);
315 ASSERT_EQ(err, 12);
316 slc_cb(slc_cb_data);
317 err = read(sock[1], buf, 256);
318
319 /* Fake that HF supports mSBC codec. */
320 err = write(sock[1], "AT+BAC=1,2\r", 11);
321 ASSERT_EQ(err, 11);
322 slc_cb(slc_cb_data);
323 err = read(sock[1], buf, 256);
324
325 /* Fake event reporting command to indicate SLC established. */
326 err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
327 ASSERT_EQ(err, 16);
328 slc_cb(slc_cb_data);
329
330 /* Assert that AG side prefers mSBC codec. */
331 codec = hfp_slc_get_selected_codec(handle);
332 EXPECT_EQ(HFP_CODEC_ID_MSBC, codec);
333
334 /* Fake HF selects mSBC codec. */
335 err = write(sock[1], "AT+BCS=2\r", 9);
336 ASSERT_EQ(err, 9);
337
338 err = hfp_slc_codec_connection_setup(handle);
339 /* Assert CRAS initiates codec selection to mSBC. */
340 memset(buf, 0, 256);
341 err = read(sock[1], buf, 256);
342 pos = strstr(buf, "\r\n+BCS:2\r\n");
343 ASSERT_NE((void*)NULL, pos);
344
345 /* Fake that HF changes supported codecs. */
346 err = write(sock[1], "AT+BAC=1\r", 9);
347 ASSERT_EQ(err, 9);
348 slc_cb(slc_cb_data);
349 err = read(sock[1], buf, 256);
350
351 /* Fake HF selects CVSD codec. */
352 err = write(sock[1], "AT+BCS=1\r", 9);
353 ASSERT_EQ(err, 9);
354
355 err = hfp_slc_codec_connection_setup(handle);
356 /* Assert CRAS initiates codec selection to CVSD. */
357 memset(buf, 0, 256);
358 err = read(sock[1], buf, 256);
359 pos = strstr(buf, "\r\n+BCS:1\r\n");
360 ASSERT_NE((void*)NULL, pos);
361
362 codec = hfp_slc_get_selected_codec(handle);
363 EXPECT_EQ(HFP_CODEC_ID_CVSD, codec);
364
365 hfp_slc_destroy(handle);
366 cras_bt_event_log_deinit(btlog);
367 }
368
369 } // namespace
370
slc_initialized_cb(struct hfp_slc_handle * handle)371 int slc_initialized_cb(struct hfp_slc_handle* handle) {
372 slc_initialized_cb_called++;
373 return 0;
374 }
375
slc_disconnected_cb(struct hfp_slc_handle * handle)376 int slc_disconnected_cb(struct hfp_slc_handle* handle) {
377 slc_disconnected_cb_called++;
378 return 0;
379 }
380
381 extern "C" {
382
383 struct cras_bt_event_log* btlog;
384
cras_system_add_select_fd(int fd,void (* callback)(void * data),void * callback_data)385 int cras_system_add_select_fd(int fd,
386 void (*callback)(void* data),
387 void* callback_data) {
388 cras_system_add_select_fd_called++;
389 slc_cb = callback;
390 slc_cb_data = callback_data;
391 return 0;
392 }
393
cras_system_rm_select_fd(int fd)394 void cras_system_rm_select_fd(int fd) {}
395
cras_bt_device_address(struct cras_bt_device * device)396 const char* cras_bt_device_address(struct cras_bt_device* device) {
397 return "";
398 }
399
cras_bt_device_update_hardware_volume(struct cras_bt_device * device,int volume)400 void cras_bt_device_update_hardware_volume(struct cras_bt_device* device,
401 int volume) {
402 cras_bt_device_update_hardware_volume_called++;
403 }
404
cras_observer_notify_bt_battery_changed(const char * address,uint32_t level)405 void cras_observer_notify_bt_battery_changed(const char* address,
406 uint32_t level) {
407 cras_observer_notify_bt_batter_changed_called++;
408 }
409
410 /* To return fake errno */
__errno_location()411 int* __errno_location() {
412 return &fake_errno;
413 }
414
cras_system_state_get_tm()415 struct cras_tm* cras_system_state_get_tm() {
416 return NULL;
417 }
418
cras_tm_create_timer(struct cras_tm * tm,unsigned int ms,void (* cb)(struct cras_timer * t,void * data),void * cb_data)419 struct cras_timer* cras_tm_create_timer(struct cras_tm* tm,
420 unsigned int ms,
421 void (*cb)(struct cras_timer* t,
422 void* data),
423 void* cb_data) {
424 cras_tm_timer_cb = cb;
425 cras_tm_timer_cb_data = cb_data;
426 return reinterpret_cast<struct cras_timer*>(0x404);
427 }
428
cras_poll(struct pollfd * fds,nfds_t nfds,struct timespec * timeout,const sigset_t * sigmask)429 int cras_poll(struct pollfd* fds,
430 nfds_t nfds,
431 struct timespec* timeout,
432 const sigset_t* sigmask) {
433 return 1;
434 }
435
cras_tm_cancel_timer(struct cras_tm * tm,struct cras_timer * t)436 void cras_tm_cancel_timer(struct cras_tm* tm, struct cras_timer* t) {}
437 }
438
439 // For telephony
cras_telephony_get()440 struct cras_telephony_handle* cras_telephony_get() {
441 return &fake_telephony;
442 }
443
cras_telephony_store_dial_number(int len,const char * num)444 void cras_telephony_store_dial_number(int len, const char* num) {}
445
cras_telephony_event_answer_call()446 int cras_telephony_event_answer_call() {
447 return 0;
448 }
449
cras_telephony_event_terminate_call()450 int cras_telephony_event_terminate_call() {
451 return 0;
452 }
453
main(int argc,char ** argv)454 int main(int argc, char** argv) {
455 ::testing::InitGoogleTest(&argc, argv);
456 return RUN_ALL_TESTS();
457 }
458