• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (c) 2014 The Android Open Source Project
4  *  Copyright 2009-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 /*******************************************************************************
21  *
22  *  Filename:      btif_hf_client.c
23  *
24  *  Description:   Handsfree Profile (HF role) Bluetooth Interface
25  *
26  *  Notes:
27  *  a) Lifecycle of a control block
28  *  Control block handles the lifecycle for a particular remote device's
29  *  connection. The connection can go via the classic phases but more
30  *  importantly there's only two messages from BTA that affect this.
31  *  BTA_HF_CLIENT_OPEN_EVT and BTA_HF_CLIENT_CLOSE_EVT. Since the API between
32  *  BTIF and BTA is controlled entirely by handles it's important to know where
33  *  the handles are created and destroyed. Handles can be created at two
34  *  locations:
35  *  -- While connect() is called from BTIF. This is an outgoing connection
36  *  -- While accepting an incoming connection (see BTA_HF_CLIENT_OPEN_EVT
37  *  handling).
38  *
39  *  The destruction or rather reuse of handles can be done when
40  *  BTA_HF_CLIENT_CLOSE_EVT is called. Refer to the event handling for details
41  *  of this.
42  *
43  ******************************************************************************/
44 
45 #ifndef LOG_TAG
46 #define LOG_TAG "bt_btif_hfc"
47 #endif
48 
49 #include <hardware/bluetooth.h>
50 #include <hardware/bt_hf_client.h>
51 #include <string.h>
52 
53 #include "bta_hf_client_api.h"
54 #include "btif_common.h"
55 #include "btif_profile_queue.h"
56 #include "btif_util.h"
57 #include "osi/include/osi.h"
58 #include "osi/include/properties.h"
59 #include "types/raw_address.h"
60 
61 #include <base/logging.h>
62 
63 /*******************************************************************************
64  *  Constants & Macros
65  ******************************************************************************/
66 
67 #ifndef BTIF_HF_CLIENT_SERVICE_NAME
68 #define BTIF_HF_CLIENT_SERVICE_NAME ("Handsfree")
69 #endif
70 
71 /*******************************************************************************
72  *  Local type definitions
73  ******************************************************************************/
74 /* BTIF-HF control block to map bdaddr to BTA handle */
75 typedef struct {
76   uint16_t handle;                       // Handle obtained frm the BTA
77   RawAddress peer_bda;                   // Device corresponding to handle
78   bthf_client_connection_state_t state;  // State of current connection
79   tBTA_HF_CLIENT_PEER_FEAT peer_feat;    // HF features
80   tBTA_HF_CLIENT_CHLD_FEAT chld_feat;    // AT+CHLD=<> command features
81 } btif_hf_client_cb_t;
82 
83 /* Max devices supported by BTIF (useful to match the value in BTA) */
84 #define HF_CLIENT_MAX_DEVICES 10
85 typedef struct {
86   btif_hf_client_cb_t cb[HF_CLIENT_MAX_DEVICES];
87 } btif_hf_client_cb_arr_t;
88 
89 /******************************************************************************
90  * Local function declarations
91  ******************************************************************************/
92 btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle);
93 btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& addr);
94 bool is_connected(const btif_hf_client_cb_t* cb);
95 
96 /*******************************************************************************
97  *  Static variables
98  ******************************************************************************/
99 static bthf_client_callbacks_t* bt_hf_client_callbacks = NULL;
100 
101 char btif_hf_client_version[PROPERTY_VALUE_MAX];
102 
dump_hf_client_conn_state(uint16_t event)103 static const char* dump_hf_client_conn_state(uint16_t event) {
104   switch (event) {
105     CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED)
106     CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_CONNECTING)
107     CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_CONNECTED)
108     CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED)
109     CASE_RETURN_STR(BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING)
110     default:
111       return "UNKNOWN MSG ID";
112   }
113 }
114 
115 #define CHECK_BTHF_CLIENT_INIT()                                        \
116   do {                                                                  \
117     if (bt_hf_client_callbacks == NULL) {                               \
118       BTIF_TRACE_WARNING("BTHF CLIENT: %s: not initialized", __func__); \
119       return BT_STATUS_NOT_READY;                                       \
120     } else {                                                            \
121       BTIF_TRACE_EVENT("BTHF CLIENT: %s", __func__);                    \
122     }                                                                   \
123   } while (0)
124 
125 #define CHECK_BTHF_CLIENT_SLC_CONNECTED(cb)                                  \
126   do {                                                                       \
127     if (bt_hf_client_callbacks == NULL) {                                    \
128       BTIF_TRACE_WARNING("BTHF CLIENT: %s: not initialized", __func__);      \
129       return BT_STATUS_NOT_READY;                                            \
130     } else if ((cb)->state != BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) {  \
131       BTIF_TRACE_WARNING("BTHF CLIENT: %s: SLC connection not up. state=%s", \
132                          __func__, dump_hf_client_conn_state((cb)->state));  \
133       return BT_STATUS_NOT_READY;                                            \
134     } else {                                                                 \
135       BTIF_TRACE_EVENT("BTHF CLIENT: %s", __func__);                         \
136     }                                                                        \
137   } while (0)
138 
139 static btif_hf_client_cb_arr_t btif_hf_client_cb_arr;
140 
141 /*******************************************************************************
142  *  Static functions
143  ******************************************************************************/
144 
145 /*******************************************************************************
146  *
147  * Function        btif_in_hf_client_generic_evt
148  *
149  * Description     Processes generic events to be sent to JNI that are not
150  *                 triggered from the BTA.
151  *                 Always runs in BTIF context
152  *
153  * Returns          void
154  *
155  ******************************************************************************/
btif_in_hf_client_generic_evt(uint16_t event,char * p_param)156 static void btif_in_hf_client_generic_evt(uint16_t event, char* p_param) {
157   BTIF_TRACE_DEBUG("%s", __func__);
158   RawAddress* bd_addr = (RawAddress*)p_param;
159   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
160   if (cb == NULL || !is_connected(cb)) {
161     BTIF_TRACE_ERROR("%s: failed to find block for bda", __func__);
162     return;
163   }
164 
165   BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
166   switch (event) {
167     case BTIF_HF_CLIENT_CB_AUDIO_CONNECTING: {
168       HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
169                 (bthf_client_audio_state_t)BTHF_CLIENT_AUDIO_STATE_CONNECTING);
170     } break;
171     default: {
172       BTIF_TRACE_WARNING("%s: : Unknown event 0x%x", __func__, event);
173     } break;
174   }
175 }
176 
177 /*******************************************************************************
178  *  Functions
179  ******************************************************************************/
is_connected(const btif_hf_client_cb_t * cb)180 bool is_connected(const btif_hf_client_cb_t* cb) {
181   if ((cb->state == BTHF_CLIENT_CONNECTION_STATE_CONNECTED) ||
182       (cb->state == BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED))
183     return true;
184 
185   BTIF_TRACE_ERROR("%s: not connected!", __func__);
186   return false;
187 }
188 
189 /*******************************************************************************
190  *
191  * Function        btif_hf_client_get_cb_by_handle
192  *
193  * Description     Get control block by handle
194  *
195  * Returns         btif_hf_client_cb_t pointer if available NULL otherwise
196  *
197  ******************************************************************************/
btif_hf_client_get_cb_by_handle(uint16_t handle)198 btif_hf_client_cb_t* btif_hf_client_get_cb_by_handle(uint16_t handle) {
199   BTIF_TRACE_DEBUG("%s: cb by handle %d", __func__, handle);
200   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
201     // Block is valid only if it is allocated i.e. state is not DISCONNECTED
202     if (btif_hf_client_cb_arr.cb[i].state !=
203             BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED &&
204         btif_hf_client_cb_arr.cb[i].handle == handle) {
205       return &btif_hf_client_cb_arr.cb[i];
206     }
207   }
208   BTIF_TRACE_ERROR("%s: could not find block for handle %d", __func__, handle);
209   return NULL;
210 }
211 
212 /*******************************************************************************
213  *
214  * Function        btif_hf_client_get_cb_by_bda
215  *
216  * Description     Get control block by bda
217  *
218  * Returns         btif_hf_client_cb_t pointer if available NULL otherwise
219  *
220  ******************************************************************************/
btif_hf_client_get_cb_by_bda(const RawAddress & bd_addr)221 btif_hf_client_cb_t* btif_hf_client_get_cb_by_bda(const RawAddress& bd_addr) {
222   VLOG(1) << __func__ << " incoming addr " << ADDRESS_TO_LOGGABLE_CSTR(bd_addr);
223 
224   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
225     // Block is valid only if it is allocated i.e. state is not DISCONNECTED
226     if (btif_hf_client_cb_arr.cb[i].state !=
227             BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED &&
228         btif_hf_client_cb_arr.cb[i].peer_bda == bd_addr) {
229       return &btif_hf_client_cb_arr.cb[i];
230     }
231   }
232   BTIF_TRACE_ERROR("%s: could not find block for bdaddr", __func__);
233   return NULL;
234 }
235 
236 /*******************************************************************************
237  *
238  * Function        btif_hf_client_allocate_cb
239  *
240  * Description     Get control block by bda
241  *
242  * Returns         btif_hf_client_cb_t pointer if available NULL otherwise
243  *
244  ******************************************************************************/
btif_hf_client_allocate_cb()245 btif_hf_client_cb_t* btif_hf_client_allocate_cb() {
246   for (int i = 0; i < HF_CLIENT_MAX_DEVICES; i++) {
247     btif_hf_client_cb_t* cb = &btif_hf_client_cb_arr.cb[i];
248     if (cb->state == BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED) {
249       return cb;
250     }
251   }
252   BTIF_TRACE_ERROR("%s: unable to allocate control block", __func__);
253   return NULL;
254 }
255 
256 /*****************************************************************************
257  *
258  *   btif hf api functions (no context switch)
259  *
260  ****************************************************************************/
261 
262 /*******************************************************************************
263  *
264  * Function         btif_hf_client_init
265  *
266  * Description     initializes the hf interface
267  *
268  * Returns         bt_status_t
269  *
270  ******************************************************************************/
init(bthf_client_callbacks_t * callbacks)271 static bt_status_t init(bthf_client_callbacks_t* callbacks) {
272   BTIF_TRACE_EVENT("%s", __func__);
273 
274   bt_hf_client_callbacks = callbacks;
275 
276   btif_enable_service(BTA_HFP_HS_SERVICE_ID);
277 
278   memset(&btif_hf_client_cb_arr, 0, sizeof(btif_hf_client_cb_arr_t));
279 
280   return BT_STATUS_SUCCESS;
281 }
282 
283 /*******************************************************************************
284  *
285  * Function         connect
286  *
287  * Description     connect to audio gateway
288  *
289  * Returns         bt_status_t
290  *
291  ******************************************************************************/
connect_int(RawAddress * bd_addr,uint16_t uuid)292 static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) {
293   btif_hf_client_cb_t* cb = btif_hf_client_allocate_cb();
294   if (cb == NULL) {
295     BTIF_TRACE_ERROR("%s: could not allocate block!", __func__);
296     return BT_STATUS_BUSY;
297   }
298 
299   cb->peer_bda = *bd_addr;
300   if (is_connected(cb)) return BT_STATUS_BUSY;
301 
302   cb->state = BTHF_CLIENT_CONNECTION_STATE_CONNECTING;
303   cb->peer_bda = *bd_addr;
304 
305   /* Open HF connection to remote device and get the relevant handle.
306    * The handle is valid until we have called BTA_HfClientClose or the LL
307    * has notified us of channel close due to remote closing, error etc.
308    */
309   return BTA_HfClientOpen(cb->peer_bda, &cb->handle);
310 }
311 
connect(const RawAddress * bd_addr)312 static bt_status_t connect(const RawAddress* bd_addr) {
313   BTIF_TRACE_EVENT("HFP Client version is  %s", btif_hf_client_version);
314   CHECK_BTHF_CLIENT_INIT();
315   return btif_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int);
316 }
317 
318 /*******************************************************************************
319  *
320  * Function         disconnect
321  *
322  * Description      disconnect from audio gateway
323  *
324  * Returns         bt_status_t
325  *
326  ******************************************************************************/
disconnect(const RawAddress * bd_addr)327 static bt_status_t disconnect(const RawAddress* bd_addr) {
328   CHECK_BTHF_CLIENT_INIT();
329 
330   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
331   if (cb != NULL) {
332     BTA_HfClientClose(cb->handle);
333     return BT_STATUS_SUCCESS;
334   } else {
335     return BT_STATUS_BUSY;
336   }
337 }
338 
339 /*******************************************************************************
340  *
341  * Function         connect_audio
342  *
343  * Description     create an audio connection
344  *
345  * Returns         bt_status_t
346  *
347  ******************************************************************************/
connect_audio(const RawAddress * bd_addr)348 static bt_status_t connect_audio(const RawAddress* bd_addr) {
349   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
350   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
351 
352   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
353 
354   if ((get_default_hf_client_features() & BTA_HF_CLIENT_FEAT_CODEC) &&
355       (cb->peer_feat & BTA_HF_CLIENT_PEER_CODEC)) {
356     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BCC, 0, 0, NULL);
357   } else {
358     BTA_HfClientAudioOpen(cb->handle);
359   }
360 
361   /* Inform the application that the audio connection has been initiated
362    * successfully */
363   btif_transfer_context(btif_in_hf_client_generic_evt,
364                         BTIF_HF_CLIENT_CB_AUDIO_CONNECTING, (char*)bd_addr,
365                         sizeof(RawAddress), NULL);
366   return BT_STATUS_SUCCESS;
367 }
368 
369 /*******************************************************************************
370  *
371  * Function         disconnect_audio
372  *
373  * Description      close the audio connection
374  *
375  * Returns         bt_status_t
376  *
377  ******************************************************************************/
disconnect_audio(const RawAddress * bd_addr)378 static bt_status_t disconnect_audio(const RawAddress* bd_addr) {
379   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
380   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
381 
382   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
383 
384   BTA_HfClientAudioClose(cb->handle);
385   return BT_STATUS_SUCCESS;
386 }
387 
388 /*******************************************************************************
389  *
390  * Function         start_voice_recognition
391  *
392  * Description      start voice recognition
393  *
394  * Returns          bt_status_t
395  *
396  ******************************************************************************/
start_voice_recognition(const RawAddress * bd_addr)397 static bt_status_t start_voice_recognition(const RawAddress* bd_addr) {
398   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
399   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
400 
401   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
402 
403   if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC) {
404     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BVRA, 1, 0, NULL);
405     return BT_STATUS_SUCCESS;
406   }
407   return BT_STATUS_UNSUPPORTED;
408 }
409 
410 /*******************************************************************************
411  *
412  * Function         stop_voice_recognition
413  *
414  * Description      stop voice recognition
415  *
416  * Returns          bt_status_t
417  *
418  ******************************************************************************/
stop_voice_recognition(const RawAddress * bd_addr)419 static bt_status_t stop_voice_recognition(const RawAddress* bd_addr) {
420   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
421   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
422 
423   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
424 
425   if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC) {
426     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BVRA, 0, 0, NULL);
427     return BT_STATUS_SUCCESS;
428   }
429   return BT_STATUS_UNSUPPORTED;
430 }
431 
432 /*******************************************************************************
433  *
434  * Function         volume_control
435  *
436  * Description      volume control
437  *
438  * Returns          bt_status_t
439  *
440  ******************************************************************************/
volume_control(const RawAddress * bd_addr,bthf_client_volume_type_t type,int volume)441 static bt_status_t volume_control(const RawAddress* bd_addr,
442                                   bthf_client_volume_type_t type, int volume) {
443   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
444   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
445 
446   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
447 
448   switch (type) {
449     case BTHF_CLIENT_VOLUME_TYPE_SPK:
450       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_VGS, volume, 0, NULL);
451       break;
452     case BTHF_CLIENT_VOLUME_TYPE_MIC:
453       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_VGM, volume, 0, NULL);
454       break;
455     default:
456       return BT_STATUS_UNSUPPORTED;
457   }
458 
459   return BT_STATUS_SUCCESS;
460 }
461 
462 /*******************************************************************************
463  *
464  * Function         dial
465  *
466  * Description      place a call
467  *
468  * Returns          bt_status_t
469  *
470  ******************************************************************************/
dial(UNUSED_ATTR const RawAddress * bd_addr,const char * number)471 static bt_status_t dial(UNUSED_ATTR const RawAddress* bd_addr,
472                         const char* number) {
473   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
474   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
475 
476   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
477 
478   if (number) {
479     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATD, 0, 0, number);
480   } else {
481     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BLDN, 0, 0, NULL);
482   }
483   return BT_STATUS_SUCCESS;
484 }
485 
486 /*******************************************************************************
487  *
488  * Function         dial_memory
489  *
490  * Description      place a call with number specified by location (speed dial)
491  *
492  * Returns          bt_status_t
493  *
494  ******************************************************************************/
dial_memory(const RawAddress * bd_addr,int location)495 static bt_status_t dial_memory(const RawAddress* bd_addr, int location) {
496   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
497   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
498 
499   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
500 
501   BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATD, location, 0, NULL);
502   return BT_STATUS_SUCCESS;
503 }
504 
505 /*******************************************************************************
506  *
507  * Function         handle_call_action
508  *
509  * Description      handle specified call related action
510  *
511  * Returns          bt_status_t
512  *
513  ******************************************************************************/
handle_call_action(const RawAddress * bd_addr,bthf_client_call_action_t action,int idx)514 static bt_status_t handle_call_action(const RawAddress* bd_addr,
515                                       bthf_client_call_action_t action,
516                                       int idx) {
517   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
518   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
519 
520   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
521 
522   switch (action) {
523     case BTHF_CLIENT_CALL_ACTION_CHLD_0:
524       if (cb->chld_feat & BTA_HF_CLIENT_CHLD_REL) {
525         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 0, 0, NULL);
526         break;
527       }
528       return BT_STATUS_UNSUPPORTED;
529     case BTHF_CLIENT_CALL_ACTION_CHLD_1:
530       // CHLD 1 is mandatory for 3 way calling
531       if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
532         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, 0, NULL);
533         break;
534       }
535       return BT_STATUS_UNSUPPORTED;
536     case BTHF_CLIENT_CALL_ACTION_CHLD_2:
537       // CHLD 2 is mandatory for 3 way calling
538       if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
539         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, 0, NULL);
540         break;
541       }
542       return BT_STATUS_UNSUPPORTED;
543     case BTHF_CLIENT_CALL_ACTION_CHLD_3:
544       if (cb->chld_feat & BTA_HF_CLIENT_CHLD_MERGE) {
545         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 3, 0, NULL);
546         break;
547       }
548       return BT_STATUS_UNSUPPORTED;
549     case BTHF_CLIENT_CALL_ACTION_CHLD_4:
550       if (cb->chld_feat & BTA_HF_CLIENT_CHLD_MERGE_DETACH) {
551         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 4, 0, NULL);
552         break;
553       }
554       return BT_STATUS_UNSUPPORTED;
555     case BTHF_CLIENT_CALL_ACTION_CHLD_1x:
556       if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECC) {
557         if (idx < 1) {
558           return BT_STATUS_FAIL;
559         }
560         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, idx, NULL);
561         break;
562       }
563       return BT_STATUS_UNSUPPORTED;
564     case BTHF_CLIENT_CALL_ACTION_CHLD_2x:
565       if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECC) {
566         if (idx < 1) {
567           return BT_STATUS_FAIL;
568         }
569         BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, idx, NULL);
570         break;
571       }
572       return BT_STATUS_UNSUPPORTED;
573     case BTHF_CLIENT_CALL_ACTION_ATA:
574       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATA, 0, 0, NULL);
575       break;
576     case BTHF_CLIENT_CALL_ACTION_CHUP:
577       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHUP, 0, 0, NULL);
578       break;
579     case BTHF_CLIENT_CALL_ACTION_BTRH_0:
580       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 0, 0, NULL);
581       break;
582     case BTHF_CLIENT_CALL_ACTION_BTRH_1:
583       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 1, 0, NULL);
584       break;
585     case BTHF_CLIENT_CALL_ACTION_BTRH_2:
586       BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 2, 0, NULL);
587       break;
588     default:
589       return BT_STATUS_FAIL;
590   }
591 
592   return BT_STATUS_SUCCESS;
593 }
594 
595 /*******************************************************************************
596  *
597  * Function         query_current_calls
598  *
599  * Description      query list of current calls
600  *
601  * Returns          bt_status_t
602  *
603  ******************************************************************************/
query_current_calls(UNUSED_ATTR const RawAddress * bd_addr)604 static bt_status_t query_current_calls(UNUSED_ATTR const RawAddress* bd_addr) {
605   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
606   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
607 
608   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
609 
610   if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECS) {
611     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CLCC, 0, 0, NULL);
612     return BT_STATUS_SUCCESS;
613   }
614 
615   return BT_STATUS_UNSUPPORTED;
616 }
617 
618 /*******************************************************************************
619  *
620  * Function         query_current_operator_name
621  *
622  * Description      query current selected operator name
623  *
624  * Returns          bt_status_t
625  *
626  ******************************************************************************/
query_current_operator_name(const RawAddress * bd_addr)627 static bt_status_t query_current_operator_name(const RawAddress* bd_addr) {
628   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
629   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
630 
631   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
632 
633   BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_COPS, 0, 0, NULL);
634   return BT_STATUS_SUCCESS;
635 }
636 
637 /*******************************************************************************
638  *
639  * Function         retieve_subscriber_info
640  *
641  * Description      retrieve subscriber number information
642  *
643  * Returns          bt_status_t
644  *
645  ******************************************************************************/
retrieve_subscriber_info(const RawAddress * bd_addr)646 static bt_status_t retrieve_subscriber_info(const RawAddress* bd_addr) {
647   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
648   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
649 
650   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
651 
652   BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CNUM, 0, 0, NULL);
653   return BT_STATUS_SUCCESS;
654 }
655 
656 /*******************************************************************************
657  *
658  * Function         send_dtmf
659  *
660  * Description      send dtmf
661  *
662  * Returns          bt_status_t
663  *
664  ******************************************************************************/
send_dtmf(const RawAddress * bd_addr,char code)665 static bt_status_t send_dtmf(const RawAddress* bd_addr, char code) {
666   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
667   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
668 
669   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
670 
671   BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_VTS, code, 0, NULL);
672   return BT_STATUS_SUCCESS;
673 }
674 
675 /*******************************************************************************
676  *
677  * Function         request_last_voice_tag_number
678  *
679  * Description      Request number from AG for VR purposes
680  *
681  * Returns          bt_status_t
682  *
683  ******************************************************************************/
request_last_voice_tag_number(const RawAddress * bd_addr)684 static bt_status_t request_last_voice_tag_number(const RawAddress* bd_addr) {
685   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
686   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
687 
688   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
689 
690   if (cb->peer_feat & BTA_HF_CLIENT_PEER_VTAG) {
691     BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BINP, 1, 0, NULL);
692     return BT_STATUS_SUCCESS;
693   }
694   return BT_STATUS_UNSUPPORTED;
695 }
696 
697 /*******************************************************************************
698  *
699  * Function         cleanup
700  *
701  * Description      Closes the HF interface
702  *
703  * Returns          bt_status_t
704  *
705  ******************************************************************************/
cleanup(void)706 static void cleanup(void) {
707   BTIF_TRACE_EVENT("%s", __func__);
708 
709   btif_queue_cleanup(UUID_SERVCLASS_HF_HANDSFREE);
710   if (bt_hf_client_callbacks) {
711     btif_disable_service(BTA_HFP_HS_SERVICE_ID);
712     bt_hf_client_callbacks = NULL;
713   }
714 }
715 
716 /*******************************************************************************
717  *
718  * Function         send_at_cmd
719  *
720  * Description      Send requested AT command to rempte device.
721  *
722  * Returns          bt_status_t
723  *
724  ******************************************************************************/
send_at_cmd(const RawAddress * bd_addr,int cmd,int val1,int val2,const char * arg)725 static bt_status_t send_at_cmd(const RawAddress* bd_addr, int cmd, int val1,
726                                int val2, const char* arg) {
727   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
728   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
729 
730   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
731 
732   BTIF_TRACE_EVENT("%s: Cmd %d val1 %d val2 %d arg %s", __func__, cmd, val1,
733                    val2, (arg != NULL) ? arg : "<null>");
734   BTA_HfClientSendAT(cb->handle, cmd, val1, val2, arg);
735 
736   return BT_STATUS_SUCCESS;
737 }
738 
739 /*******************************************************************************
740  *
741  * Function         send_hfp_audio_policy
742  *
743  * Description      Send requested audio policies to remote device.
744  *
745  * Returns          bt_status_t
746  *
747  ******************************************************************************/
send_android_at(const RawAddress * bd_addr,const char * arg)748 static bt_status_t send_android_at(const RawAddress* bd_addr, const char* arg) {
749   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
750   if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;
751 
752   CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);
753 
754   BTIF_TRACE_EVENT("%s: val1 %s", __func__, arg);
755   BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ANDROID, 0, 0, arg);
756 
757   return BT_STATUS_SUCCESS;
758 }
759 
760 static const bthf_client_interface_t bthfClientInterface = {
761     .size = sizeof(bthf_client_interface_t),
762     .init = init,
763     .connect = connect,
764     .disconnect = disconnect,
765     .connect_audio = connect_audio,
766     .disconnect_audio = disconnect_audio,
767     .start_voice_recognition = start_voice_recognition,
768     .stop_voice_recognition = stop_voice_recognition,
769     .volume_control = volume_control,
770     .dial = dial,
771     .dial_memory = dial_memory,
772     .handle_call_action = handle_call_action,
773     .query_current_calls = query_current_calls,
774     .query_current_operator_name = query_current_operator_name,
775     .retrieve_subscriber_info = retrieve_subscriber_info,
776     .send_dtmf = send_dtmf,
777     .request_last_voice_tag_number = request_last_voice_tag_number,
778     .cleanup = cleanup,
779     .send_at_cmd = send_at_cmd,
780     .send_android_at = send_android_at,
781 };
782 
process_ind_evt(tBTA_HF_CLIENT_IND * ind)783 static void process_ind_evt(tBTA_HF_CLIENT_IND* ind) {
784   BTIF_TRACE_DEBUG("%s", __func__);
785 
786   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(ind->bd_addr);
787   if (cb == NULL || !is_connected(cb)) return;
788 
789   switch (ind->type) {
790     case BTA_HF_CLIENT_IND_CALL:
791       HAL_CBACK(bt_hf_client_callbacks, call_cb, &cb->peer_bda,
792                 (bthf_client_call_t)ind->value);
793       break;
794 
795     case BTA_HF_CLIENT_IND_CALLSETUP:
796       HAL_CBACK(bt_hf_client_callbacks, callsetup_cb, &cb->peer_bda,
797                 (bthf_client_callsetup_t)ind->value);
798       break;
799     case BTA_HF_CLIENT_IND_CALLHELD:
800       HAL_CBACK(bt_hf_client_callbacks, callheld_cb, &cb->peer_bda,
801                 (bthf_client_callheld_t)ind->value);
802       break;
803 
804     case BTA_HF_CLIENT_IND_SERVICE:
805       HAL_CBACK(bt_hf_client_callbacks, network_state_cb, &cb->peer_bda,
806                 (bthf_client_network_state_t)ind->value);
807       break;
808 
809     case BTA_HF_CLIENT_IND_SIGNAL:
810       HAL_CBACK(bt_hf_client_callbacks, network_signal_cb, &cb->peer_bda,
811                 ind->value);
812       break;
813 
814     case BTA_HF_CLIENT_IND_ROAM:
815       HAL_CBACK(bt_hf_client_callbacks, network_roaming_cb, &cb->peer_bda,
816                 (bthf_client_service_type_t)ind->value);
817       break;
818 
819     case BTA_HF_CLIENT_IND_BATTCH:
820       HAL_CBACK(bt_hf_client_callbacks, battery_level_cb, &cb->peer_bda,
821                 ind->value);
822       break;
823 
824     default:
825       break;
826   }
827 }
828 
829 /*******************************************************************************
830  *
831  * Function         btif_hf_client_upstreams_evt
832  *
833  * Description      Executes HF CLIENT UPSTREAMS events in btif context
834  *
835  * Returns          void
836  *
837  ******************************************************************************/
btif_hf_client_upstreams_evt(uint16_t event,char * p_param)838 static void btif_hf_client_upstreams_evt(uint16_t event, char* p_param) {
839   tBTA_HF_CLIENT* p_data = (tBTA_HF_CLIENT*)p_param;
840 
841   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(p_data->bd_addr);
842   if (cb == NULL && event == BTA_HF_CLIENT_OPEN_EVT) {
843     BTIF_TRACE_DEBUG("%s: event BTA_HF_CLIENT_OPEN_EVT allocating block",
844                      __func__);
845     cb = btif_hf_client_allocate_cb();
846     if (cb == NULL) {
847       BTIF_TRACE_ERROR("%s: event BTA_HF_CLIENT_OPEN_EVT failed to allocate cb",
848                        __func__, event);
849       return;
850     }
851     cb->handle = p_data->open.handle;
852     cb->peer_bda = p_data->open.bd_addr;
853   } else if (cb == NULL) {
854     BTIF_TRACE_ERROR("%s: event %d but not allocating block: cb not found",
855                      __func__, event);
856     return;
857   }
858 
859   BTIF_TRACE_DEBUG("%s: event=%s (%u)", __func__, dump_hf_client_event(event),
860                    event);
861 
862   switch (event) {
863     case BTA_HF_CLIENT_OPEN_EVT:
864       if (p_data->open.status == BTA_HF_CLIENT_SUCCESS) {
865         cb->state = BTHF_CLIENT_CONNECTION_STATE_CONNECTED;
866         cb->peer_feat = 0;
867         cb->chld_feat = 0;
868         cb->handle = p_data->open.handle;
869       } else if (cb->state == BTHF_CLIENT_CONNECTION_STATE_CONNECTING) {
870         cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
871       } else {
872         BTIF_TRACE_WARNING(
873             "%s: HF CLient open failed, but another device connected. "
874             "status=%d state=%d connected device=%s",
875             __func__, p_data->open.status, cb->state,
876             ADDRESS_TO_LOGGABLE_CSTR(cb->peer_bda));
877         break;
878       }
879 
880       HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
881                 cb->state, 0, /* peer feat */
882                 0 /* AT+CHLD feat */);
883 
884       if (cb->state == BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED)
885         cb->peer_bda = RawAddress::kAny;
886 
887       if (p_data->open.status != BTA_HF_CLIENT_SUCCESS) btif_queue_advance();
888       break;
889 
890     case BTA_HF_CLIENT_CONN_EVT:
891       cb->peer_feat = p_data->conn.peer_feat;
892       cb->chld_feat = p_data->conn.chld_feat;
893       cb->state = BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED;
894 
895       HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
896                 cb->state, cb->peer_feat, cb->chld_feat);
897 
898       /* Inform the application about in-band ringtone */
899       if (cb->peer_feat & BTA_HF_CLIENT_PEER_INBAND) {
900         HAL_CBACK(bt_hf_client_callbacks, in_band_ring_tone_cb, &cb->peer_bda,
901                   BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED);
902       }
903 
904       btif_queue_advance();
905       break;
906 
907     case BTA_HF_CLIENT_CLOSE_EVT:
908       cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
909       HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
910                 cb->state, 0, 0);
911       cb->peer_bda = RawAddress::kAny;
912       cb->peer_feat = 0;
913       cb->chld_feat = 0;
914       cb->handle = 0;
915 
916       /* Clean up any btif_hf_client_cb for the same disconnected bd_addr.
917        * when there is an Incoming hf_client connection is in progress and
918        * at the same time, outgoing hf_client connection is initiated then
919        * due to race condition two btif_hf_client_cb is created. This creates
920        * problem for successive connections
921        */
922       while ((cb = btif_hf_client_get_cb_by_bda(p_data->bd_addr)) != NULL) {
923         cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
924         cb->peer_bda = RawAddress::kAny;
925         cb->peer_feat = 0;
926         cb->chld_feat = 0;
927         cb->handle = 0;
928       }
929 
930       btif_queue_advance();
931       break;
932 
933     case BTA_HF_CLIENT_IND_EVT:
934       process_ind_evt(&p_data->ind);
935       break;
936 
937     case BTA_HF_CLIENT_MIC_EVT:
938       HAL_CBACK(bt_hf_client_callbacks, volume_change_cb, &cb->peer_bda,
939                 BTHF_CLIENT_VOLUME_TYPE_MIC, p_data->val.value);
940       break;
941 
942     case BTA_HF_CLIENT_SPK_EVT:
943       HAL_CBACK(bt_hf_client_callbacks, volume_change_cb, &cb->peer_bda,
944                 BTHF_CLIENT_VOLUME_TYPE_SPK, p_data->val.value);
945       break;
946 
947     case BTA_HF_CLIENT_VOICE_REC_EVT:
948       HAL_CBACK(bt_hf_client_callbacks, vr_cmd_cb, &cb->peer_bda,
949                 (bthf_client_vr_state_t)p_data->val.value);
950       break;
951 
952     case BTA_HF_CLIENT_OPERATOR_NAME_EVT:
953       HAL_CBACK(bt_hf_client_callbacks, current_operator_cb, &cb->peer_bda,
954                 p_data->operator_name.name);
955       break;
956 
957     case BTA_HF_CLIENT_CLIP_EVT:
958       HAL_CBACK(bt_hf_client_callbacks, clip_cb, &cb->peer_bda,
959                 p_data->number.number);
960       break;
961 
962     case BTA_HF_CLIENT_BINP_EVT:
963       HAL_CBACK(bt_hf_client_callbacks, last_voice_tag_number_callback,
964                 &cb->peer_bda, p_data->number.number);
965       break;
966 
967     case BTA_HF_CLIENT_CCWA_EVT:
968       HAL_CBACK(bt_hf_client_callbacks, call_waiting_cb, &cb->peer_bda,
969                 p_data->number.number);
970       break;
971 
972     case BTA_HF_CLIENT_AT_RESULT_EVT:
973       HAL_CBACK(bt_hf_client_callbacks, cmd_complete_cb, &cb->peer_bda,
974                 (bthf_client_cmd_complete_t)p_data->result.type,
975                 p_data->result.cme);
976       break;
977 
978     case BTA_HF_CLIENT_CLCC_EVT:
979       HAL_CBACK(bt_hf_client_callbacks, current_calls_cb, &cb->peer_bda,
980                 p_data->clcc.idx,
981                 p_data->clcc.inc ? BTHF_CLIENT_CALL_DIRECTION_INCOMING
982                                  : BTHF_CLIENT_CALL_DIRECTION_OUTGOING,
983                 (bthf_client_call_state_t)p_data->clcc.status,
984                 p_data->clcc.mpty ? BTHF_CLIENT_CALL_MPTY_TYPE_MULTI
985                                   : BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE,
986                 p_data->clcc.number_present ? p_data->clcc.number : "");
987       break;
988 
989     case BTA_HF_CLIENT_CNUM_EVT:
990       if (p_data->cnum.service == 4) {
991         HAL_CBACK(bt_hf_client_callbacks, subscriber_info_cb, &cb->peer_bda,
992                   p_data->cnum.number, BTHF_CLIENT_SERVICE_VOICE);
993       } else if (p_data->cnum.service == 5) {
994         HAL_CBACK(bt_hf_client_callbacks, subscriber_info_cb, &cb->peer_bda,
995                   p_data->cnum.number, BTHF_CLIENT_SERVICE_FAX);
996       } else {
997         HAL_CBACK(bt_hf_client_callbacks, subscriber_info_cb, &cb->peer_bda,
998                   p_data->cnum.number, BTHF_CLIENT_SERVICE_UNKNOWN);
999       }
1000       break;
1001 
1002     case BTA_HF_CLIENT_BTRH_EVT:
1003       if (p_data->val.value <= BTRH_CLIENT_RESP_AND_HOLD_REJECT) {
1004         HAL_CBACK(bt_hf_client_callbacks, resp_and_hold_cb, &cb->peer_bda,
1005                   (bthf_client_resp_and_hold_t)p_data->val.value);
1006       }
1007       break;
1008 
1009     case BTA_HF_CLIENT_BSIR_EVT:
1010       if (p_data->val.value != 0) {
1011         HAL_CBACK(bt_hf_client_callbacks, in_band_ring_tone_cb, &cb->peer_bda,
1012                   BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED);
1013       } else {
1014         HAL_CBACK(bt_hf_client_callbacks, in_band_ring_tone_cb, &cb->peer_bda,
1015                   BTHF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED);
1016       }
1017       break;
1018 
1019     case BTA_HF_CLIENT_AUDIO_OPEN_EVT:
1020       HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
1021                 BTHF_CLIENT_AUDIO_STATE_CONNECTED);
1022       break;
1023 
1024     case BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT:
1025       HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
1026                 BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC);
1027       break;
1028 
1029     case BTA_HF_CLIENT_AUDIO_CLOSE_EVT:
1030       HAL_CBACK(bt_hf_client_callbacks, audio_state_cb, &cb->peer_bda,
1031                 BTHF_CLIENT_AUDIO_STATE_DISCONNECTED);
1032       break;
1033     case BTA_HF_CLIENT_RING_INDICATION:
1034       HAL_CBACK(bt_hf_client_callbacks, ring_indication_cb, &cb->peer_bda);
1035       break;
1036     case BTA_HF_CLIENT_UNKNOWN_EVT:
1037       HAL_CBACK(bt_hf_client_callbacks, unknown_event_cb, &cb->peer_bda,
1038                 p_data->unknown.event_string);
1039       break;
1040     default:
1041       BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
1042       break;
1043   }
1044 }
1045 
1046 /*******************************************************************************
1047  *
1048  * Function         bta_hf_client_evt
1049  *
1050  * Description      Switches context from BTA to BTIF for all HF Client events
1051  *
1052  * Returns          void
1053  *
1054  ******************************************************************************/
1055 
bta_hf_client_evt(tBTA_HF_CLIENT_EVT event,tBTA_HF_CLIENT * p_data)1056 static void bta_hf_client_evt(tBTA_HF_CLIENT_EVT event,
1057                               tBTA_HF_CLIENT* p_data) {
1058   bt_status_t status;
1059 
1060   /* switch context to btif task context (copy full union size for convenience)
1061    */
1062   status = btif_transfer_context(btif_hf_client_upstreams_evt, (uint16_t)event,
1063                                  (char*)p_data, sizeof(*p_data), NULL);
1064 
1065   /* catch any failed context transfers */
1066   ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
1067 }
1068 
1069 /*******************************************************************************
1070  *
1071  * Function         btif_hf_client_execute_service
1072  *
1073  * Description      Initializes/Shuts down the service
1074  *
1075  * Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1076  *
1077  ******************************************************************************/
btif_hf_client_execute_service(bool b_enable)1078 bt_status_t btif_hf_client_execute_service(bool b_enable) {
1079   BTIF_TRACE_EVENT("%s: enable: %d", __func__, b_enable);
1080 
1081   tBTA_HF_CLIENT_FEAT features = get_default_hf_client_features();
1082   uint16_t hfp_version = get_default_hfp_version();
1083   if (hfp_version >= HFP_VERSION_1_7) {
1084     features |= BTA_HF_CLIENT_FEAT_ESCO_S4;
1085   }
1086 
1087   if (b_enable) {
1088     /* Enable and register with BTA-HFClient */
1089     BTIF_TRACE_EVENT("%s: support codec negotiation %d ", __func__,
1090                      features);
1091     BTA_HfClientEnable(bta_hf_client_evt, features,
1092                        BTIF_HF_CLIENT_SERVICE_NAME);
1093   } else {
1094     BTA_HfClientDisable();
1095   }
1096   return BT_STATUS_SUCCESS;
1097 }
1098 
1099 /*******************************************************************************
1100  *
1101  * Function         btif_hf_get_interface
1102  *
1103  * Description      Get the hf callback interface
1104  *
1105  * Returns          bthf_interface_t
1106  *
1107  ******************************************************************************/
btif_hf_client_get_interface(void)1108 const bthf_client_interface_t* btif_hf_client_get_interface(void) {
1109   BTIF_TRACE_EVENT("%s", __func__);
1110   return &bthfClientInterface;
1111 }
1112