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