• 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 #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 slc_initialized_cb_called;
21 static int slc_disconnected_cb_called;
22 static int cras_system_add_select_fd_called;
23 static void (*slc_cb)(void* data);
24 static void* slc_cb_data;
25 static int fake_errno;
26 static struct cras_bt_device* device =
27     reinterpret_cast<struct cras_bt_device*>(2);
28 static void (*cras_tm_timer_cb)(struct cras_timer* t, void* data);
29 static void* cras_tm_timer_cb_data;
30 
31 int slc_initialized_cb(struct hfp_slc_handle* handle);
32 int slc_disconnected_cb(struct hfp_slc_handle* handle);
33 
ResetStubData()34 void ResetStubData() {
35   slc_initialized_cb_called = 0;
36   cras_system_add_select_fd_called = 0;
37   cras_bt_device_update_hardware_volume_called = 0;
38   slc_cb = NULL;
39   slc_cb_data = NULL;
40 }
41 
42 namespace {
43 
TEST(HfpSlc,CreateSlcHandle)44 TEST(HfpSlc, CreateSlcHandle) {
45   ResetStubData();
46 
47   handle = hfp_slc_create(0, 0, AG_ENHANCED_CALL_STATUS, device,
48                           slc_initialized_cb, slc_disconnected_cb);
49   ASSERT_EQ(1, cras_system_add_select_fd_called);
50   ASSERT_EQ(handle, slc_cb_data);
51 
52   hfp_slc_destroy(handle);
53 }
54 
TEST(HfpSlc,InitializeSlc)55 TEST(HfpSlc, InitializeSlc) {
56   int err;
57   int sock[2];
58   char buf[256];
59   char* chp;
60   ResetStubData();
61 
62   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
63   handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device,
64                           slc_initialized_cb, slc_disconnected_cb);
65 
66   err = write(sock[1], "AT+CIND=?\r", 10);
67   ASSERT_EQ(10, err);
68   slc_cb(slc_cb_data);
69   err = read(sock[1], buf, 256);
70 
71   /* Assert "\r\n+CIND: ... \r\n" response is received */
72   chp = strstr(buf, "\r\n");
73   ASSERT_NE((void*)NULL, (void*)chp);
74   ASSERT_EQ(0, strncmp("\r\n+CIND:", chp, 8));
75   chp += 2;
76   chp = strstr(chp, "\r\n");
77   ASSERT_NE((void*)NULL, (void*)chp);
78 
79   /* Assert "\r\nOK\r\n" response is received */
80   chp += 2;
81   chp = strstr(chp, "\r\n");
82   ASSERT_NE((void*)NULL, (void*)chp);
83   ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
84 
85   err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
86   ASSERT_EQ(16, err);
87   slc_cb(slc_cb_data);
88 
89   ASSERT_EQ(1, slc_initialized_cb_called);
90 
91   /* Assert "\r\nOK\r\n" response is received */
92   err = read(sock[1], buf, 256);
93 
94   chp = strstr(buf, "\r\n");
95   ASSERT_NE((void*)NULL, (void*)chp);
96   ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
97 
98   err = write(sock[1], "AT+VGS=13\r", 10);
99   ASSERT_EQ(err, 10);
100   slc_cb(slc_cb_data);
101 
102   err = read(sock[1], buf, 256);
103 
104   chp = strstr(buf, "\r\n");
105   ASSERT_NE((void*)NULL, (void*)chp);
106   ASSERT_EQ(0, strncmp("\r\nOK", chp, 4));
107 
108   ASSERT_EQ(1, cras_bt_device_update_hardware_volume_called);
109 
110   hfp_slc_destroy(handle);
111 }
112 
TEST(HfpSlc,DisconnectSlc)113 TEST(HfpSlc, DisconnectSlc) {
114   int sock[2];
115   ResetStubData();
116 
117   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
118   handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device,
119                           slc_initialized_cb, slc_disconnected_cb);
120   /* Close socket right away to make read() get negative err code, and
121    * fake the errno to ECONNRESET. */
122   close(sock[0]);
123   close(sock[1]);
124   fake_errno = 104;
125   slc_cb(slc_cb_data);
126 
127   ASSERT_EQ(1, slc_disconnected_cb_called);
128 
129   hfp_slc_destroy(handle);
130 }
131 
TEST(HfpSlc,CodecNegotiation)132 TEST(HfpSlc, CodecNegotiation) {
133   int codec;
134   int err;
135   int sock[2];
136   char buf[256];
137   char* pos;
138   ResetStubData();
139 
140   btlog = cras_bt_event_log_init();
141 
142   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
143   handle = hfp_slc_create(sock[0], 0, AG_CODEC_NEGOTIATION, device,
144                           slc_initialized_cb, slc_disconnected_cb);
145 
146   codec = hfp_slc_get_selected_codec(handle);
147   EXPECT_EQ(HFP_CODEC_ID_CVSD, codec);
148 
149   /* Fake that HF supports codec negotiation. */
150   err = write(sock[1], "AT+BRSF=128\r", 12);
151   ASSERT_EQ(err, 12);
152   slc_cb(slc_cb_data);
153   err = read(sock[1], buf, 256);
154 
155   /* Fake that HF supports mSBC codec. */
156   err = write(sock[1], "AT+BAC=1,2\r", 11);
157   ASSERT_EQ(err, 11);
158   slc_cb(slc_cb_data);
159   err = read(sock[1], buf, 256);
160 
161   /* Fake event reporting command to indicate SLC established. */
162   err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
163   ASSERT_EQ(err, 16);
164   slc_cb(slc_cb_data);
165 
166   /* Assert that AG side prefers mSBC codec. */
167   codec = hfp_slc_get_selected_codec(handle);
168   EXPECT_EQ(HFP_CODEC_ID_MSBC, codec);
169 
170   /* Assert CRAS initiates codec selection to mSBC. */
171   memset(buf, 0, 256);
172   err = read(sock[1], buf, 256);
173   pos = strstr(buf, "\r\n+BCS:2\r\n");
174   ASSERT_NE((void*)NULL, pos);
175 
176   err = write(sock[1], "AT+VGS=9\r", 9);
177   ASSERT_EQ(err, 9);
178   slc_cb(slc_cb_data);
179 
180   /* Assert CRAS initiates codec selection to mSBC. */
181   memset(buf, 0, 256);
182   err = read(sock[1], buf, 256);
183   pos = strstr(buf, "\r\n+BCS:2\r\n");
184   ASSERT_NE((void*)NULL, pos);
185 
186   /* Fake that receiving codec selection from HF. */
187   err = write(sock[1], "AT+BCS=2\r", 9);
188   ASSERT_EQ(err, 9);
189   slc_cb(slc_cb_data);
190 
191   memset(buf, 0, 256);
192   err = read(sock[1], buf, 256);
193   pos = strstr(buf, "\r\n+BCS:2\r\n");
194   ASSERT_EQ((void*)NULL, pos);
195 
196   hfp_slc_destroy(handle);
197   cras_bt_event_log_deinit(btlog);
198 }
199 
TEST(HfpSlc,CodecNegotiationTimeout)200 TEST(HfpSlc, CodecNegotiationTimeout) {
201   int codec;
202   int err;
203   int sock[2];
204   char buf[256];
205   char* pos;
206   ResetStubData();
207 
208   btlog = cras_bt_event_log_init();
209 
210   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
211   handle = hfp_slc_create(sock[0], 0, AG_CODEC_NEGOTIATION, device,
212                           slc_initialized_cb, slc_disconnected_cb);
213 
214   codec = hfp_slc_get_selected_codec(handle);
215   EXPECT_EQ(HFP_CODEC_ID_CVSD, codec);
216 
217   /* Fake that HF supports codec negotiation. */
218   err = write(sock[1], "AT+BRSF=128\r", 12);
219   ASSERT_EQ(err, 12);
220   slc_cb(slc_cb_data);
221   err = read(sock[1], buf, 256);
222 
223   /* Fake that HF supports mSBC codec. */
224   err = write(sock[1], "AT+BAC=1,2\r", 11);
225   ASSERT_EQ(err, 11);
226   slc_cb(slc_cb_data);
227   err = read(sock[1], buf, 256);
228 
229   /* Fake event reporting command to indicate SLC established. */
230   err = write(sock[1], "AT+CMER=3,0,0,1\r", 16);
231   ASSERT_EQ(err, 16);
232   slc_cb(slc_cb_data);
233 
234   ASSERT_NE((void*)NULL, cras_tm_timer_cb);
235 
236   /* Assert that AG side prefers mSBC codec. */
237   codec = hfp_slc_get_selected_codec(handle);
238   EXPECT_EQ(HFP_CODEC_ID_MSBC, codec);
239 
240   /* Assert CRAS initiates codec selection to mSBC. */
241   memset(buf, 0, 256);
242   err = read(sock[1], buf, 256);
243   pos = strstr(buf, "\r\n+BCS:2\r\n");
244   ASSERT_NE((void*)NULL, pos);
245 
246   /* Assume codec negotiation failed. so timeout is reached. */
247   cras_tm_timer_cb(NULL, cras_tm_timer_cb_data);
248 
249   codec = hfp_slc_get_selected_codec(handle);
250   EXPECT_EQ(HFP_CODEC_ID_CVSD, codec);
251 
252   /* Expects CRAS fallback and selects to CVSD codec. */
253   memset(buf, 0, 256);
254   err = read(sock[1], buf, 256);
255   pos = strstr(buf, "\r\n+BCS:1\r\n");
256   ASSERT_NE((void*)NULL, pos);
257 
258   hfp_slc_destroy(handle);
259   cras_bt_event_log_deinit(btlog);
260 }
261 
262 }  // namespace
263 
slc_initialized_cb(struct hfp_slc_handle * handle)264 int slc_initialized_cb(struct hfp_slc_handle* handle) {
265   slc_initialized_cb_called++;
266   return 0;
267 }
268 
slc_disconnected_cb(struct hfp_slc_handle * handle)269 int slc_disconnected_cb(struct hfp_slc_handle* handle) {
270   slc_disconnected_cb_called++;
271   return 0;
272 }
273 
274 extern "C" {
275 
276 struct cras_bt_event_log* btlog;
277 
cras_system_add_select_fd(int fd,void (* callback)(void * data),void * callback_data)278 int cras_system_add_select_fd(int fd,
279                               void (*callback)(void* data),
280                               void* callback_data) {
281   cras_system_add_select_fd_called++;
282   slc_cb = callback;
283   slc_cb_data = callback_data;
284   return 0;
285 }
286 
cras_system_rm_select_fd(int fd)287 void cras_system_rm_select_fd(int fd) {}
288 
cras_bt_device_update_hardware_volume(struct cras_bt_device * device,int volume)289 void cras_bt_device_update_hardware_volume(struct cras_bt_device* device,
290                                            int volume) {
291   cras_bt_device_update_hardware_volume_called++;
292 }
293 
294 /* To return fake errno */
__errno_location()295 int* __errno_location() {
296   return &fake_errno;
297 }
298 
cras_system_state_get_tm()299 struct cras_tm* cras_system_state_get_tm() {
300   return NULL;
301 }
302 
cras_tm_create_timer(struct cras_tm * tm,unsigned int ms,void (* cb)(struct cras_timer * t,void * data),void * cb_data)303 struct cras_timer* cras_tm_create_timer(struct cras_tm* tm,
304                                         unsigned int ms,
305                                         void (*cb)(struct cras_timer* t,
306                                                    void* data),
307                                         void* cb_data) {
308   cras_tm_timer_cb = cb;
309   cras_tm_timer_cb_data = cb_data;
310   return reinterpret_cast<struct cras_timer*>(0x404);
311 }
312 
cras_tm_cancel_timer(struct cras_tm * tm,struct cras_timer * t)313 void cras_tm_cancel_timer(struct cras_tm* tm, struct cras_timer* t) {}
314 }
315 
316 // For telephony
cras_telephony_get()317 struct cras_telephony_handle* cras_telephony_get() {
318   return &fake_telephony;
319 }
320 
cras_telephony_store_dial_number(int len,const char * num)321 void cras_telephony_store_dial_number(int len, const char* num) {}
322 
cras_telephony_event_answer_call()323 int cras_telephony_event_answer_call() {
324   return 0;
325 }
326 
cras_telephony_event_terminate_call()327 int cras_telephony_event_terminate_call() {
328   return 0;
329 }
330 
main(int argc,char ** argv)331 int main(int argc, char** argv) {
332   ::testing::InitGoogleTest(&argc, argv);
333   return RUN_ALL_TESTS();
334 }
335