• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (c) 2016 The Android Open Source Project
4  *  Copyright 2003-2012 Broadcom Corporation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 
20 #include <cstdint>
21 #include <cstdio>
22 
23 #include "bta/hf_client/bta_hf_client_int.h"
24 #include "bta/include/utl.h"
25 #include "osi/include/allocator.h"
26 #include "osi/include/osi.h"  // UNUSED_ATTR
27 #include "stack/include/bt_hdr.h"
28 #include "stack/include/btm_api.h"
29 #include "types/raw_address.h"
30 
31 #include <base/logging.h>
32 
33 static const char* bta_hf_client_evt_str(uint16_t event);
34 static const char* bta_hf_client_state_str(uint8_t state);
35 void bta_hf_client_cb_init(tBTA_HF_CLIENT_CB* client_cb, uint16_t handle);
36 
37 /* state machine states */
38 enum {
39   BTA_HF_CLIENT_INIT_ST,
40   BTA_HF_CLIENT_OPENING_ST,
41   BTA_HF_CLIENT_OPEN_ST,
42   BTA_HF_CLIENT_CLOSING_ST
43 };
44 
45 /* state machine action enumeration list */
46 enum {
47   BTA_HF_CLIENT_RFC_DO_CLOSE,
48   BTA_HF_CLIENT_START_CLOSE,
49   BTA_HF_CLIENT_START_OPEN,
50   BTA_HF_CLIENT_RFC_ACP_OPEN,
51   BTA_HF_CLIENT_SCO_LISTEN,
52   BTA_HF_CLIENT_SCO_CONN_OPEN,
53   BTA_HF_CLIENT_SCO_CONN_CLOSE,
54   BTA_HF_CLIENT_SCO_OPEN,
55   BTA_HF_CLIENT_SCO_CLOSE,
56   BTA_HF_CLIENT_FREE_DB,
57   BTA_HF_CLIENT_OPEN_FAIL,
58   BTA_HF_CLIENT_RFC_OPEN,
59   BTA_HF_CLIENT_RFC_FAIL,
60   BTA_HF_CLIENT_DISC_INT_RES,
61   BTA_HF_CLIENT_RFC_DO_OPEN,
62   BTA_HF_CLIENT_DISC_FAIL,
63   BTA_HF_CLIENT_RFC_CLOSE,
64   BTA_HF_CLIENT_RFC_DATA,
65   BTA_HF_CLIENT_DISC_ACP_RES,
66   BTA_HF_CLIENT_SVC_CONN_OPEN,
67   BTA_HF_CLIENT_SEND_AT_CMD,
68   BTA_HF_CLIENT_NUM_ACTIONS,
69 };
70 
71 #define BTA_HF_CLIENT_IGNORE BTA_HF_CLIENT_NUM_ACTIONS
72 
73 /* type for action functions */
74 typedef void (*tBTA_HF_CLIENT_ACTION)(tBTA_HF_CLIENT_DATA* p_data);
75 
76 /* action functions table, indexed with action enum */
77 const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = {
78     /* BTA_HF_CLIENT_RFC_DO_CLOSE */ bta_hf_client_rfc_do_close,
79     /* BTA_HF_CLIENT_START_CLOSE */ bta_hf_client_start_close,
80     /* BTA_HF_CLIENT_START_OPEN */ bta_hf_client_start_open,
81     /* BTA_HF_CLIENT_RFC_ACP_OPEN */ bta_hf_client_rfc_acp_open,
82     /* BTA_HF_CLIENT_SCO_LISTEN */ NULL,
83     /* BTA_HF_CLIENT_SCO_CONN_OPEN */ bta_hf_client_sco_conn_open,
84     /* BTA_HF_CLIENT_SCO_CONN_CLOSE*/ bta_hf_client_sco_conn_close,
85     /* BTA_HF_CLIENT_SCO_OPEN */ bta_hf_client_sco_open,
86     /* BTA_HF_CLIENT_SCO_CLOSE */ bta_hf_client_sco_close,
87     /* BTA_HF_CLIENT_FREE_DB */ bta_hf_client_free_db,
88     /* BTA_HF_CLIENT_OPEN_FAIL */ bta_hf_client_open_fail,
89     /* BTA_HF_CLIENT_RFC_OPEN */ bta_hf_client_rfc_open,
90     /* BTA_HF_CLIENT_RFC_FAIL */ bta_hf_client_rfc_fail,
91     /* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res,
92     /* BTA_HF_CLIENT_RFC_DO_OPEN */ bta_hf_client_rfc_do_open,
93     /* BTA_HF_CLIENT_DISC_FAIL */ bta_hf_client_disc_fail,
94     /* BTA_HF_CLIENT_RFC_CLOSE */ bta_hf_client_rfc_close,
95     /* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data,
96     /* BTA_HF_CLIENT_DISC_ACP_RES */ bta_hf_client_disc_acp_res,
97     /* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open,
98     /* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd,
99 };
100 
101 /* state table information */
102 #define BTA_HF_CLIENT_ACTIONS 2    /* number of actions */
103 #define BTA_HF_CLIENT_NEXT_STATE 2 /* position of next state */
104 #define BTA_HF_CLIENT_NUM_COLS 3   /* number of columns in state tables */
105 
106 /* state table for init state */
107 const uint8_t bta_hf_client_st_init[][BTA_HF_CLIENT_NUM_COLS] = {
108     /* Event                    Action 1                       Action 2
109        Next state */
110     /* API_OPEN_EVT */ {BTA_HF_CLIENT_START_OPEN, BTA_HF_CLIENT_IGNORE,
111                         BTA_HF_CLIENT_OPENING_ST},
112     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
113                          BTA_HF_CLIENT_INIT_ST},
114     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
115                               BTA_HF_CLIENT_INIT_ST},
116     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
117                                BTA_HF_CLIENT_INIT_ST},
118     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_ACP_OPEN, BTA_HF_CLIENT_IGNORE,
119                         BTA_HF_CLIENT_OPEN_ST},
120     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
121                          BTA_HF_CLIENT_INIT_ST},
122     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
123                              BTA_HF_CLIENT_INIT_ST},
124     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
125                         BTA_HF_CLIENT_INIT_ST},
126     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE,
127                             BTA_HF_CLIENT_INIT_ST},
128     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
129                             BTA_HF_CLIENT_INIT_ST},
130     /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
131                        BTA_HF_CLIENT_INIT_ST},
132     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
133                          BTA_HF_CLIENT_INIT_ST},
134     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
135                         BTA_HF_CLIENT_INIT_ST},
136     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
137                          BTA_HF_CLIENT_INIT_ST},
138     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
139                            BTA_HF_CLIENT_INIT_ST},
140 };
141 
142 /* state table for opening state */
143 const uint8_t bta_hf_client_st_opening[][BTA_HF_CLIENT_NUM_COLS] = {
144     /* Event                    Action 1                       Action 2
145        Next state */
146     /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE,
147                         BTA_HF_CLIENT_OPENING_ST},
148     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_DO_CLOSE, BTA_HF_CLIENT_IGNORE,
149                          BTA_HF_CLIENT_CLOSING_ST},
150     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
151                               BTA_HF_CLIENT_OPENING_ST},
152     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
153                                BTA_HF_CLIENT_OPENING_ST},
154     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_OPEN, BTA_HF_CLIENT_IGNORE,
155                         BTA_HF_CLIENT_OPEN_ST},
156     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_FAIL, BTA_HF_CLIENT_IGNORE,
157                          BTA_HF_CLIENT_INIT_ST},
158     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
159                              BTA_HF_CLIENT_OPENING_ST},
160     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
161                         BTA_HF_CLIENT_OPENING_ST},
162     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
163                             BTA_HF_CLIENT_OPENING_ST},
164     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_DISC_INT_RES, BTA_HF_CLIENT_IGNORE,
165                             BTA_HF_CLIENT_OPENING_ST},
166     /* DISC_OK_EVT */ {BTA_HF_CLIENT_RFC_DO_OPEN, BTA_HF_CLIENT_IGNORE,
167                        BTA_HF_CLIENT_OPENING_ST},
168     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_DISC_FAIL, BTA_HF_CLIENT_IGNORE,
169                          BTA_HF_CLIENT_INIT_ST},
170     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
171                         BTA_HF_CLIENT_OPENING_ST},
172     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
173                          BTA_HF_CLIENT_OPENING_ST},
174     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
175                            BTA_HF_CLIENT_OPENING_ST},
176 };
177 
178 /* state table for open state */
179 const uint8_t bta_hf_client_st_open[][BTA_HF_CLIENT_NUM_COLS] = {
180     /* Event                    Action 1                       Action 2
181        Next state */
182     /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE,
183                         BTA_HF_CLIENT_OPEN_ST},
184     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_START_CLOSE, BTA_HF_CLIENT_IGNORE,
185                          BTA_HF_CLIENT_CLOSING_ST},
186     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_OPEN, BTA_HF_CLIENT_IGNORE,
187                               BTA_HF_CLIENT_OPEN_ST},
188     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CLOSE, BTA_HF_CLIENT_IGNORE,
189                                BTA_HF_CLIENT_OPEN_ST},
190     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
191                         BTA_HF_CLIENT_OPEN_ST},
192     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE,
193                          BTA_HF_CLIENT_INIT_ST},
194     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
195                              BTA_HF_CLIENT_OPEN_ST},
196     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_RFC_DATA, BTA_HF_CLIENT_IGNORE,
197                         BTA_HF_CLIENT_OPEN_ST},
198     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_DISC_ACP_RES, BTA_HF_CLIENT_IGNORE,
199                             BTA_HF_CLIENT_OPEN_ST},
200     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
201                             BTA_HF_CLIENT_OPEN_ST},
202     /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
203                        BTA_HF_CLIENT_OPEN_ST},
204     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
205                          BTA_HF_CLIENT_OPEN_ST},
206     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_CONN_OPEN, BTA_HF_CLIENT_IGNORE,
207                         BTA_HF_CLIENT_OPEN_ST},
208     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE,
209                          BTA_HF_CLIENT_OPEN_ST},
210     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_SEND_AT_CMD, BTA_HF_CLIENT_IGNORE,
211                            BTA_HF_CLIENT_OPEN_ST},
212 };
213 
214 /* state table for closing state */
215 const uint8_t bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = {
216     /* Event                    Action 1                       Action 2
217        Next state */
218     /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE,
219                         BTA_HF_CLIENT_CLOSING_ST},
220     /* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
221                          BTA_HF_CLIENT_CLOSING_ST},
222     /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
223                               BTA_HF_CLIENT_CLOSING_ST},
224     /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
225                                BTA_HF_CLIENT_CLOSING_ST},
226     /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
227                         BTA_HF_CLIENT_CLOSING_ST},
228     /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE,
229                          BTA_HF_CLIENT_INIT_ST},
230     /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
231                              BTA_HF_CLIENT_CLOSING_ST},
232     /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
233                         BTA_HF_CLIENT_CLOSING_ST},
234     /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE,
235                             BTA_HF_CLIENT_CLOSING_ST},
236     /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE,
237                             BTA_HF_CLIENT_INIT_ST},
238     /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
239                        BTA_HF_CLIENT_CLOSING_ST},
240     /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
241                          BTA_HF_CLIENT_CLOSING_ST},
242     /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
243                         BTA_HF_CLIENT_CLOSING_ST},
244     /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
245                          BTA_HF_CLIENT_CLOSING_ST},
246     /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE,
247                            BTA_HF_CLIENT_CLOSING_ST},
248 };
249 
250 /* type for state table */
251 typedef const uint8_t (*tBTA_HF_CLIENT_ST_TBL)[BTA_HF_CLIENT_NUM_COLS];
252 
253 /* state table */
254 const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = {
255     bta_hf_client_st_init, bta_hf_client_st_opening, bta_hf_client_st_open,
256     bta_hf_client_st_closing};
257 
258 /* HF Client control block */
259 tBTA_HF_CLIENT_CB_ARR bta_hf_client_cb_arr;
260 
261 /* Event handler for the state machine */
262 static const tBTA_SYS_REG bta_hf_client_reg = {bta_hf_client_hdl_event,
263                                                BTA_HfClientDisable};
264 
265 /*******************************************************************************
266  *
267  * Function         bta_hf_client_cb_arr_init
268  *
269  * Description      Initialize entire control block array set
270  *
271  *
272  * Returns          void
273  *
274  ******************************************************************************/
bta_hf_client_cb_arr_init()275 void bta_hf_client_cb_arr_init() {
276   memset(&bta_hf_client_cb_arr, 0, sizeof(tBTA_HF_CLIENT_CB_ARR));
277 
278   // reset the handles and make the CBs non-allocated
279   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
280     // Allocate the handles in increasing order of indices
281     bta_hf_client_cb_init(&(bta_hf_client_cb_arr.cb[i]), i);
282     bta_hf_client_cb_arr.cb[i].handle = BTA_HF_CLIENT_CB_FIRST_HANDLE + i;
283   }
284 }
285 
286 /*******************************************************************************
287  *
288  * Function         bta_hf_client_cb_init
289  *
290  * Description      Initialize an HF_Client service control block. Assign the
291  *                  handle to cb->handle.
292  *
293  *
294  *
295  * Returns          void
296  *
297  ******************************************************************************/
bta_hf_client_cb_init(tBTA_HF_CLIENT_CB * client_cb,uint16_t handle)298 void bta_hf_client_cb_init(tBTA_HF_CLIENT_CB* client_cb, uint16_t handle) {
299   APPL_TRACE_DEBUG("%s", __func__);
300 
301   // Free any memory we need to explicity release
302   alarm_free(client_cb->collision_timer);
303 
304   // release unique pointers
305   client_cb->enabled_hf_indicators.clear();
306   client_cb->peer_hf_indicators.clear();
307 
308   // Memset the rest of the block
309   // memset(client_cb, 0, sizeof(tBTA_HF_CLIENT_CB));
310   *client_cb = {};
311 
312   // Re allocate any variables required
313   client_cb->collision_timer = alarm_new("bta_hf_client.scb_collision_timer");
314   client_cb->handle = handle;
315   client_cb->sco_idx = BTM_INVALID_SCO_INDEX;
316 }
317 
318 /*******************************************************************************
319  *
320  * Function         bta_hf_client_resume_open
321  *
322  * Description      Resume opening process.
323  *
324  *
325  * Returns          void
326  *
327  ******************************************************************************/
bta_hf_client_resume_open(tBTA_HF_CLIENT_CB * client_cb)328 void bta_hf_client_resume_open(tBTA_HF_CLIENT_CB* client_cb) {
329   APPL_TRACE_DEBUG("%s", __func__);
330 
331   /* resume opening process.  */
332   if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
333     client_cb->state = BTA_HF_CLIENT_OPENING_ST;
334     tBTA_HF_CLIENT_DATA msg;
335     msg.hdr.layer_specific = client_cb->handle;
336     msg.api_open.bd_addr = client_cb->peer_addr;
337     bta_hf_client_start_open(&msg);
338   }
339 }
340 
341 /*******************************************************************************
342  *
343  * Function         bta_hf_client_collision_timer_cback
344  *
345  * Description      HF Client connection collision timer callback
346  *
347  *
348  * Returns          void
349  *
350  ******************************************************************************/
bta_hf_client_collision_timer_cback(void * data)351 static void bta_hf_client_collision_timer_cback(void* data) {
352   APPL_TRACE_DEBUG("%s", __func__);
353   tBTA_HF_CLIENT_CB* client_cb = (tBTA_HF_CLIENT_CB*)data;
354 
355   /* If the peer haven't opened connection, restart opening process */
356   bta_hf_client_resume_open(client_cb);
357 }
358 
359 /*******************************************************************************
360  *
361  * Function         bta_hf_client_collision_cback
362  *
363  * Description      Get notified about collision.
364  *
365  *
366  * Returns          void
367  *
368  ******************************************************************************/
bta_hf_client_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status,uint8_t id,UNUSED_ATTR uint8_t app_id,const RawAddress & peer_addr)369 void bta_hf_client_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status,
370                                    uint8_t id, UNUSED_ATTR uint8_t app_id,
371                                    const RawAddress& peer_addr) {
372   tBTA_HF_CLIENT_CB* client_cb = bta_hf_client_find_cb_by_bda(peer_addr);
373   if (client_cb != NULL && client_cb->state == BTA_HF_CLIENT_OPENING_ST) {
374     if (id == BTA_ID_SYS) /* ACL collision */
375     {
376       APPL_TRACE_WARNING("HF Client found collision (ACL) ...");
377     } else if (id == BTA_ID_HS) /* RFCOMM collision */
378     {
379       APPL_TRACE_WARNING("HF Client found collision (RFCOMM) ...");
380     } else {
381       APPL_TRACE_WARNING("HF Client found collision (\?\?\?) ...");
382     }
383 
384     client_cb->state = BTA_HF_CLIENT_INIT_ST;
385 
386     /* Cancel SDP if it had been started. */
387     if (client_cb->p_disc_db) {
388       (void)SDP_CancelServiceSearch(client_cb->p_disc_db);
389       osi_free_and_reset((void**)&client_cb->p_disc_db);
390     }
391 
392     /* reopen registered server */
393     /* Collision may be detected before or after we close servers. */
394     bta_hf_client_start_server();
395 
396     /* Start timer to handle connection opening restart */
397     alarm_set_on_mloop(client_cb->collision_timer,
398                        BTA_HF_CLIENT_COLLISION_TIMER_MS,
399                        bta_hf_client_collision_timer_cback, (void*)client_cb);
400   }
401 }
402 
403 /*******************************************************************************
404  *
405  * Function         bta_hf_client_api_enable
406  *
407  * Description      Handle an API enable event.
408  *
409  *
410  * Returns          void
411  *
412  ******************************************************************************/
bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK * p_cback,tBTA_HF_CLIENT_FEAT features,const char * p_service_name)413 tBTA_STATUS bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK* p_cback,
414                                      tBTA_HF_CLIENT_FEAT features,
415                                      const char* p_service_name) {
416   /* If already registered then return error */
417   if (bta_sys_is_register(BTA_ID_HS)) {
418     APPL_TRACE_ERROR("BTA HF Client is already enabled, ignoring ...");
419     return BTA_FAILURE;
420   }
421 
422   /* register with BTA system manager */
423   bta_sys_register(BTA_ID_HS, &bta_hf_client_reg);
424 
425   /* reset the control blocks */
426   bta_hf_client_cb_arr_init();
427 
428   bta_hf_client_cb_arr.p_cback = p_cback;
429   bta_hf_client_cb_arr.features = features;
430 
431   /* create SDP records */
432   bta_hf_client_create_record(&bta_hf_client_cb_arr, p_service_name);
433 
434   /* set same setting as AG does */
435   BTM_WriteVoiceSettings(AG_VOICE_SETTINGS);
436 
437   bta_sys_collision_register(BTA_ID_HS, bta_hf_client_collision_cback);
438 
439   /* Set the Audio service class bit */
440   tBTA_UTL_COD cod = {
441     .minor = BTM_COD_MINOR_UNCLASSIFIED,
442     .major = BTM_COD_MAJOR_UNCLASSIFIED,
443     .service = BTM_COD_SERVICE_AUDIO,
444   };
445   utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
446 
447   /* start RFCOMM server */
448   bta_hf_client_start_server();
449 
450   return BTA_SUCCESS;
451 }
452 
453 /*******************************************************************************
454  *
455  * Function         bta_hf_client_find_cb_by_handle
456  *
457  * Description      Finds the control block by handle provided
458  *
459  *                  handle: Handle as obtained from BTA_HfClientOpen call
460  *
461  *
462  * Returns          Control block corresponding to the handle and NULL if
463  *                  none exists
464  *
465  ******************************************************************************/
bta_hf_client_find_cb_by_handle(uint16_t handle)466 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_handle(uint16_t handle) {
467   // Handles are limited from 1 through HF_CLIENT_MAX_DEVICES
468   if (handle < 1 || handle > HF_CLIENT_MAX_DEVICES) {
469     APPL_TRACE_ERROR("%s: handle out of range (%d, %d) %d", __func__, 1,
470                      HF_CLIENT_MAX_DEVICES, handle);
471     return NULL;
472   }
473 
474   // Check if the associated index is allocated. Index is (handle - 1).
475   if (bta_hf_client_cb_arr.cb[handle - 1].is_allocated)
476     return &(bta_hf_client_cb_arr.cb[handle - 1]);
477 
478   APPL_TRACE_ERROR("%s: block not found for handle %d", __func__, handle);
479   return NULL;
480 }
481 
482 /*******************************************************************************
483  *
484  * Function         bta_hf_client_find_cb_by_bda
485  *
486  * Description      Finds the control block by handle provided
487  *
488  *                  bda: address of the device to find the handle for.
489  *                  Since there can only be one HF connection for a device
490  *                  we should always find a unique block
491  *
492  * Returns          Control block corresponding to the address and NULL if
493  *                  none exists
494  *
495  ******************************************************************************/
bta_hf_client_find_cb_by_bda(const RawAddress & peer_addr)496 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_bda(const RawAddress& peer_addr) {
497   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
498     // Check if the associated index is allocated and that BD ADDR matches
499     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
500     if (client_cb->is_allocated && peer_addr == client_cb->peer_addr) {
501       return client_cb;
502     } else {
503       APPL_TRACE_WARNING("%s: bdaddr mismatch for handle %d alloc %d", __func__,
504                          i, client_cb->is_allocated);
505     }
506   }
507   APPL_TRACE_ERROR("%s: block not found", __func__);
508   return NULL;
509 }
510 
511 /*******************************************************************************
512  *
513  * Function         bta_hf_client_find_cb_by_rfc_handle
514  *
515  * Description      Finds the control block by RFC handle provided.
516  *
517  *                  handle: RFC handle for the established connection
518  *
519  *
520  * Returns          Control block corresponding to the handle and NULL if none
521  *                  exists
522  *
523  ******************************************************************************/
bta_hf_client_find_cb_by_rfc_handle(uint16_t handle)524 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_rfc_handle(uint16_t handle) {
525   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
526     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
527     bool is_allocated = client_cb->is_allocated;
528     uint16_t conn_handle = client_cb->conn_handle;
529 
530     APPL_TRACE_DEBUG("%s: cb rfc_handle %d alloc %d conn_handle %d", __func__,
531                      handle, is_allocated, conn_handle);
532 
533     if (is_allocated && conn_handle == handle) {
534       return client_cb;
535     }
536 
537     APPL_TRACE_WARNING("%s: no cb yet %d alloc %d conn_handle %d", __func__,
538                        handle, is_allocated, conn_handle);
539   }
540 
541   APPL_TRACE_ERROR("%s: no cb found for rfc handle %d", __func__, handle);
542   return NULL;
543 }
544 
545 /*******************************************************************************
546  *
547  * Function         bta_hf_client_find_cb_by_sco_handle
548  *
549  * Description      Finds the control block by sco handle provided
550  *
551  *                  handle: sco handle
552  *
553  *
554  * Returns          Control block corresponding to the sco handle and
555  *                  none if none exists
556  *
557  ******************************************************************************/
bta_hf_client_find_cb_by_sco_handle(uint16_t handle)558 tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_sco_handle(uint16_t handle) {
559   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
560     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
561     if (client_cb->is_allocated && client_cb->sco_idx == handle) {
562       return client_cb;
563     }
564   }
565   APPL_TRACE_ERROR("%s: block not found for handle %d", __func__, handle);
566   return NULL;
567 }
568 
569 /*******************************************************************************
570  *
571  * Function         bta_hf_client_allocate_handle
572  *
573  * Description      Allocates a handle for the new BD ADDR that needs a new RF
574  *                  channel for HF connection. If the channel cannot be created
575  *                  for a reason then false is returned
576  *
577  *                  bd_addr: Address of the device for which this block is
578  *                  being created. Single device can only have one block.
579  *                  p_handle: OUT variable to store the outcome of allocate. If
580  *                  allocate failed then value is not valid
581  *
582  *
583  * Returns          true if the creation of p_handle succeeded, false otherwise
584  *
585  ******************************************************************************/
bta_hf_client_allocate_handle(const RawAddress & bd_addr,uint16_t * p_handle)586 bool bta_hf_client_allocate_handle(const RawAddress& bd_addr,
587                                    uint16_t* p_handle) {
588   tBTA_HF_CLIENT_CB* existing_cb = bta_hf_client_find_cb_by_bda(bd_addr);
589   if (existing_cb != NULL) {
590     BTIF_TRACE_ERROR("%s: cannot allocate handle since BDADDR already exists",
591                      __func__);
592     return false;
593   }
594   /* Check that we do not have a request to for same device in the control
595    * blocks */
596   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
597     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
598     if (client_cb->is_allocated) {
599       APPL_TRACE_WARNING("%s: control block already used index %d", __func__,
600                          i);
601       continue;
602     }
603 
604     // Reset the client control block
605     bta_hf_client_cb_init(client_cb, client_cb->handle);
606 
607     *p_handle = client_cb->handle;
608     APPL_TRACE_DEBUG("%s: marking CB handle %d to true", __func__,
609                      client_cb->handle);
610 
611     client_cb->is_allocated = true;
612     client_cb->peer_addr = bd_addr;
613     bta_hf_client_at_init(client_cb);
614     return true;
615   }
616 
617   return false;
618   APPL_TRACE_ERROR("%s: all control blocks in use!", __func__);
619 }
620 
621 /*******************************************************************************
622  *
623  * Function         bta_hf_client_app_callback
624  *
625  * Description      Calls the application callback
626  *
627  *
628  * Returns          Void
629  *
630  ******************************************************************************/
bta_hf_client_app_callback(uint16_t event,tBTA_HF_CLIENT * data)631 void bta_hf_client_app_callback(uint16_t event, tBTA_HF_CLIENT* data) {
632   if (bta_hf_client_cb_arr.p_cback != NULL) {
633     bta_hf_client_cb_arr.p_cback(event, data);
634   }
635 }
636 
637 /*******************************************************************************
638  *
639  * Function         bta_hf_client_api_disable
640  *
641  * Description      Handle an API disable event.
642  *
643  *
644  * Returns          void
645  *
646  ******************************************************************************/
bta_hf_client_api_disable()647 void bta_hf_client_api_disable() {
648   if (!bta_sys_is_register(BTA_ID_HS)) {
649     APPL_TRACE_WARNING("BTA HF Client is already disabled, ignoring ...");
650     return;
651   }
652 
653   /* Remove the collision handler */
654   bta_sys_collision_register(BTA_ID_HS, NULL);
655 
656   bta_hf_client_cb_arr.deregister = true;
657 
658   /* remove sdp record */
659   bta_hf_client_del_record(&bta_hf_client_cb_arr);
660 
661   /* remove rfcomm server */
662   bta_hf_client_close_server();
663 
664   /* reinit the control block */
665   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
666     if (bta_hf_client_cb_arr.cb[i].is_allocated) {
667       bta_hf_client_cb_init(&(bta_hf_client_cb_arr.cb[i]), i);
668     }
669   }
670 
671   /* De-register with BTA system manager */
672   bta_sys_deregister(BTA_ID_HS);
673 }
674 
675 /*******************************************************************************
676  *
677  * Function         bta_hf_client_hdl_event
678  *
679  * Description      Data HF Client main event handling function.
680  *
681  *
682  * Returns          bool
683  *
684  ******************************************************************************/
bta_hf_client_hdl_event(BT_HDR_RIGID * p_msg)685 bool bta_hf_client_hdl_event(BT_HDR_RIGID* p_msg) {
686   APPL_TRACE_DEBUG("%s: %s (0x%x)", __func__,
687                    bta_hf_client_evt_str(p_msg->event), p_msg->event);
688   bta_hf_client_sm_execute(p_msg->event, (tBTA_HF_CLIENT_DATA*)p_msg);
689   return true;
690 }
691 
692 /*******************************************************************************
693  *
694  * Function         bta_hf_client_sm_execute
695  *
696  * Description      State machine event handling function for HF Client
697  *
698  *
699  * Returns          void
700  *
701  ******************************************************************************/
bta_hf_client_sm_execute(uint16_t event,tBTA_HF_CLIENT_DATA * p_data)702 void bta_hf_client_sm_execute(uint16_t event, tBTA_HF_CLIENT_DATA* p_data) {
703   tBTA_HF_CLIENT_CB* client_cb =
704       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
705   if (client_cb == NULL) {
706     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
707                      p_data->hdr.layer_specific);
708     return;
709   }
710 
711   tBTA_HF_CLIENT_ST_TBL state_table;
712   uint8_t action;
713   int i;
714 
715   uint16_t in_event = event;
716   uint8_t in_state = client_cb->state;
717 
718   /* Ignore displaying of AT results when not connected (Ignored in state
719    * machine) */
720   if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
721     APPL_TRACE_EVENT("HF Client evt : State %d (%s), Event 0x%04x (%s)",
722                      client_cb->state,
723                      bta_hf_client_state_str(client_cb->state), event,
724                      bta_hf_client_evt_str(event));
725   }
726 
727   event &= 0x00FF;
728   if (event >= (BTA_HF_CLIENT_MAX_EVT & 0x00FF)) {
729     APPL_TRACE_ERROR("HF Client evt out of range, ignoring...");
730     return;
731   }
732 
733   /* look up the state table for the current state */
734   state_table = bta_hf_client_st_tbl[client_cb->state];
735 
736   /* set next state */
737   client_cb->state = state_table[event][BTA_HF_CLIENT_NEXT_STATE];
738 
739   /* execute action functions */
740   for (i = 0; i < BTA_HF_CLIENT_ACTIONS; i++) {
741     action = state_table[event][i];
742     if (action != BTA_HF_CLIENT_IGNORE) {
743       (*bta_hf_client_action[action])(p_data);
744     } else {
745       break;
746     }
747   }
748 
749   /* If the state has changed then notify the app of the corresponding change */
750   if (in_state != client_cb->state) {
751     VLOG(1) << __func__ << ": notifying state change to " << in_state << " -> "
752             << client_cb->state << " device " << client_cb->peer_addr;
753     tBTA_HF_CLIENT evt;
754     memset(&evt, 0, sizeof(evt));
755     evt.bd_addr = client_cb->peer_addr;
756     if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
757       bta_hf_client_app_callback(BTA_HF_CLIENT_CLOSE_EVT, &evt);
758       APPL_TRACE_DEBUG("%s: marking CB handle %d to false", __func__, client_cb->handle);
759       client_cb->is_allocated = false;
760     } else if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
761       evt.open.handle = client_cb->handle;
762       bta_hf_client_app_callback(BTA_HF_CLIENT_OPEN_EVT, &evt);
763     }
764   }
765 
766   VLOG(2) << __func__ << ": device " << client_cb->peer_addr
767           << "state change: [" << bta_hf_client_state_str(in_state) << "] -> ["
768           << bta_hf_client_state_str(client_cb->state) << "] after Event ["
769           << bta_hf_client_evt_str(in_event) << "]";
770 }
771 
send_post_slc_cmd(tBTA_HF_CLIENT_CB * client_cb)772 static void send_post_slc_cmd(tBTA_HF_CLIENT_CB* client_cb) {
773   client_cb->at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
774 
775   tBTA_HF_CLIENT_DATA p_data;
776   p_data.hdr.layer_specific = client_cb->handle;
777   bta_hf_client_sco_listen(&p_data);
778   bta_hf_client_send_at_bia(client_cb);
779   bta_hf_client_send_at_ccwa(client_cb, true);
780   bta_hf_client_send_at_cmee(client_cb, true);
781   bta_hf_client_send_at_cops(client_cb, false);
782   bta_hf_client_send_at_btrh(client_cb, true, 0);
783   bta_hf_client_send_at_clip(client_cb, true);
784 }
785 
786 /*******************************************************************************
787  *
788  * Function         bta_hf_client_slc_seq
789  *
790  * Description      Handles AT commands sequence required for SLC creation
791  *
792  *
793  * Returns          void
794  *
795  ******************************************************************************/
bta_hf_client_slc_seq(tBTA_HF_CLIENT_CB * client_cb,bool error)796 void bta_hf_client_slc_seq(tBTA_HF_CLIENT_CB* client_cb, bool error) {
797   APPL_TRACE_DEBUG("bta_hf_client_slc_seq cmd: %u",
798                    client_cb->at_cb.current_cmd);
799 
800   if (error) {
801     /* SLC establishment error, sent close rfcomm event */
802     APPL_TRACE_ERROR(
803         "HFPClient: Failed to create SLC due to AT error, disconnecting (%u)",
804         client_cb->at_cb.current_cmd);
805 
806     tBTA_HF_CLIENT_DATA msg;
807     msg.hdr.layer_specific = client_cb->handle;
808     bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, &msg);
809     return;
810   }
811 
812   if (client_cb->svc_conn) {
813     APPL_TRACE_WARNING("%s: SLC already connected for CB handle %d", __func__,
814                        client_cb->handle);
815     return;
816   }
817 
818   switch (client_cb->at_cb.current_cmd) {
819     case BTA_HF_CLIENT_AT_NONE:
820       bta_hf_client_send_at_brsf(client_cb, bta_hf_client_cb_arr.features);
821       break;
822 
823     case BTA_HF_CLIENT_AT_BRSF:
824       if ((bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_CODEC) &&
825           (client_cb->peer_features & BTA_HF_CLIENT_PEER_CODEC)) {
826         bta_hf_client_send_at_bac(client_cb);
827         break;
828       }
829 
830       bta_hf_client_send_at_cind(client_cb, false);
831       break;
832 
833     case BTA_HF_CLIENT_AT_BAC:
834       bta_hf_client_send_at_cind(client_cb, false);
835       break;
836 
837     case BTA_HF_CLIENT_AT_CIND:
838       bta_hf_client_send_at_cind(client_cb, true);
839       break;
840 
841     case BTA_HF_CLIENT_AT_CIND_STATUS:
842       bta_hf_client_send_at_cmer(client_cb, true);
843       break;
844 
845     case BTA_HF_CLIENT_AT_CMER:
846       if (client_cb->peer_features & BTA_HF_CLIENT_PEER_FEAT_3WAY &&
847           bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_3WAY) {
848         bta_hf_client_send_at_chld(client_cb, '?', 0);
849       } else if (bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_HF_IND &&
850                  client_cb->peer_features & BTA_HF_CLIENT_PEER_HF_IND) {
851         bta_hf_client_send_at_bind(client_cb, 0);
852       } else {
853         tBTA_HF_CLIENT_DATA msg;
854         msg.hdr.layer_specific = client_cb->handle;
855         bta_hf_client_svc_conn_open(&msg);
856         send_post_slc_cmd(client_cb);
857       }
858       break;
859 
860     case BTA_HF_CLIENT_AT_CHLD:
861       if (bta_hf_client_cb_arr.features & BTA_HF_CLIENT_FEAT_HF_IND &&
862           client_cb->peer_features & BTA_HF_CLIENT_PEER_HF_IND) {
863         bta_hf_client_send_at_bind(client_cb, 0);
864       } else {
865         tBTA_HF_CLIENT_DATA msg;
866         msg.hdr.layer_specific = client_cb->handle;
867         bta_hf_client_svc_conn_open(&msg);
868         send_post_slc_cmd(client_cb);
869       }
870       break;
871 
872     case BTA_HF_CLIENT_AT_BIND_SET_IND:
873       bta_hf_client_send_at_bind(client_cb, 1);
874       break;
875 
876     case BTA_HF_CLIENT_AT_BIND_READ_SUPPORTED_IND:
877       bta_hf_client_send_at_bind(client_cb, 2);
878       break;
879 
880     case BTA_HF_CLIENT_AT_BIND_READ_ENABLED_IND:
881       tBTA_HF_CLIENT_DATA msg;
882       msg.hdr.layer_specific = client_cb->handle;
883       bta_hf_client_svc_conn_open(&msg);
884       send_post_slc_cmd(client_cb);
885       break;
886 
887     default: {
888       /* If happen there is a bug in SLC creation procedure... */
889       APPL_TRACE_ERROR(
890           "HFPClient: Failed to create SLCdue to unexpected AT command, "
891           "disconnecting (%u)",
892           client_cb->at_cb.current_cmd);
893 
894       tBTA_HF_CLIENT_DATA msg;
895       msg.hdr.layer_specific = client_cb->handle;
896       bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, &msg);
897       break;
898     }
899   }
900 }
901 
902 #ifndef CASE_RETURN_STR
903 #define CASE_RETURN_STR(const) \
904   case const:                  \
905     return #const;
906 #endif
907 
bta_hf_client_evt_str(uint16_t event)908 static const char* bta_hf_client_evt_str(uint16_t event) {
909   switch (event) {
910     CASE_RETURN_STR(BTA_HF_CLIENT_API_OPEN_EVT)
911     CASE_RETURN_STR(BTA_HF_CLIENT_API_CLOSE_EVT)
912     CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_OPEN_EVT)
913     CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT)
914     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_OPEN_EVT)
915     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_CLOSE_EVT)
916     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT)
917     CASE_RETURN_STR(BTA_HF_CLIENT_RFC_DATA_EVT)
918     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_ACP_RES_EVT)
919     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_INT_RES_EVT)
920     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_OK_EVT)
921     CASE_RETURN_STR(BTA_HF_CLIENT_DISC_FAIL_EVT)
922     CASE_RETURN_STR(BTA_HF_CLIENT_API_ENABLE_EVT)
923     CASE_RETURN_STR(BTA_HF_CLIENT_API_DISABLE_EVT)
924     CASE_RETURN_STR(BTA_HF_CLIENT_SCO_OPEN_EVT)
925     CASE_RETURN_STR(BTA_HF_CLIENT_SCO_CLOSE_EVT)
926     CASE_RETURN_STR(BTA_HF_CLIENT_SEND_AT_CMD_EVT)
927     default:
928       return "Unknown HF Client Event";
929   }
930 }
931 
bta_hf_client_state_str(uint8_t state)932 static const char* bta_hf_client_state_str(uint8_t state) {
933   switch (state) {
934     CASE_RETURN_STR(BTA_HF_CLIENT_INIT_ST)
935     CASE_RETURN_STR(BTA_HF_CLIENT_OPENING_ST)
936     CASE_RETURN_STR(BTA_HF_CLIENT_OPEN_ST)
937     CASE_RETURN_STR(BTA_HF_CLIENT_CLOSING_ST)
938     default:
939       return "Unknown HF Client State";
940   }
941 }
942 
bta_hf_client_dump_statistics(int fd)943 void bta_hf_client_dump_statistics(int fd) {
944   dprintf(fd, "\nBluetooth HF Client BTA Statistics\n");
945 
946   // We dump statistics for all control blocks
947   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
948     tBTA_HF_CLIENT_CB* client_cb = &bta_hf_client_cb_arr.cb[i];
949     if (!client_cb->is_allocated) {
950       // Skip the blocks which are not allocated
951       continue;
952     }
953 
954     dprintf(fd, "  Control block #%d\n", i + 1);
955 
956     uint8_t* a = client_cb->peer_addr.address;
957     // Device name
958     dprintf(fd, "    Peer Device: %02x:%02x:%02x:%02x:%02x:%02x\n", a[0], a[1],
959             a[2], a[3], a[4], a[5]);
960 
961     // State machine state
962     dprintf(fd, "    State Machine State: %s\n",
963             bta_hf_client_state_str(client_cb->state));
964 
965     // Local RFC channelfor communication
966     dprintf(fd, "    RFCOMM Channel (local) %d\n", client_cb->conn_handle);
967 
968     // BTA Handle shared between BTA and client (ex BTIF)
969     dprintf(fd, "    BTA Generated handle %d\n", client_cb->handle);
970   }
971 }
972