blob: 1076006fff7243488f6b9e6517ea15d4f710aaca [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
Myles Watsonee96a3c2016-11-23 14:49:54 -080019/*******************************************************************************
The Android Open Source Project5738f832012-12-12 16:00:35 -080020 *
21 * Filename: btif_hf.c
22 *
23 * Description: Handsfree Profile Bluetooth Interface
24 *
25 *
Myles Watsonee96a3c2016-11-23 14:49:54 -080026 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080027
Marie Janssen49a86702015-07-08 11:48:57 -070028#define LOG_TAG "bt_btif_hf"
29
The Android Open Source Project5738f832012-12-12 16:00:35 -080030#include <stdlib.h>
Ian Coolidgec7503db2015-01-24 02:01:26 -080031#include <string.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070032#include <time.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080033
Marie Janssen49a86702015-07-08 11:48:57 -070034#include <hardware/bluetooth.h>
35#include <hardware/bt_hf.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080036
Satish Kodishalac75a71d2016-06-22 14:22:41 +053037#include "bta/include/utl.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080038#include "bta_ag_api.h"
Marie Janssen49a86702015-07-08 11:48:57 -070039#include "btif_common.h"
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -070040#include "btif_hf.h"
Marie Janssen49a86702015-07-08 11:48:57 -070041#include "btif_profile_queue.h"
42#include "btif_util.h"
Jack He7a9892c2017-02-02 17:42:40 -080043#include "osi/include/properties.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080044
Myles Watsonee96a3c2016-11-23 14:49:54 -080045/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -070046 * Constants & Macros
Myles Watsonee96a3c2016-11-23 14:49:54 -080047 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080048#ifndef BTIF_HSAG_SERVICE_NAME
49#define BTIF_HSAG_SERVICE_NAME ("Headset Gateway")
50#endif
51
52#ifndef BTIF_HFAG_SERVICE_NAME
53#define BTIF_HFAG_SERVICE_NAME ("Handsfree Gateway")
54#endif
55
56#ifndef BTIF_HF_SERVICES
Myles Watson6bd442f2016-10-19 09:50:22 -070057#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK | BTA_HFP_SERVICE_MASK)
The Android Open Source Project5738f832012-12-12 16:00:35 -080058#endif
59
60#ifndef BTIF_HF_SERVICE_NAMES
Myles Watson6bd442f2016-10-19 09:50:22 -070061#define BTIF_HF_SERVICE_NAMES \
62 { BTIF_HSAG_SERVICE_NAME, BTIF_HFAG_SERVICE_NAME }
The Android Open Source Project5738f832012-12-12 16:00:35 -080063#endif
64
65#ifndef BTIF_HF_SECURITY
Myles Watson6bd442f2016-10-19 09:50:22 -070066#define BTIF_HF_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
The Android Open Source Project5738f832012-12-12 16:00:35 -080067#endif
68
Matthew Xie66432dc2014-04-27 05:45:32 -070069#ifndef BTIF_HF_FEATURES
Myles Watson6bd442f2016-10-19 09:50:22 -070070#define BTIF_HF_FEATURES \
71 (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | BTA_AG_FEAT_REJECT | \
Yoshiharu Kuritaa25ef0b2015-11-25 18:00:30 +090072 BTA_AG_FEAT_ECS | BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_VREC | \
73 BTA_AG_FEAT_CODEC | BTA_AG_FEAT_HF_IND | BTA_AG_FEAT_ESCO | \
74 BTA_AG_FEAT_UNAT)
Matthew Xie66432dc2014-04-27 05:45:32 -070075#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -080076
Jack He7a9892c2017-02-02 17:42:40 -080077/* HF features supported at runtime */
78static uint32_t btif_hf_features = BTIF_HF_FEATURES;
79
Myles Watson6bd442f2016-10-19 09:50:22 -070080#define BTIF_HF_CALL_END_TIMEOUT 6
The Android Open Source Project5738f832012-12-12 16:00:35 -080081
Myles Watson6bd442f2016-10-19 09:50:22 -070082#define BTIF_HF_INVALID_IDX (-1)
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070083
84/* Number of BTIF-HF control blocks */
Myles Watson6bd442f2016-10-19 09:50:22 -070085#define BTIF_HF_NUM_CB 2
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070086
87/* Max HF clients supported from App */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070088uint16_t btif_max_hf_clients = 1;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070089
90/* HF app ids for service registration */
91typedef enum {
Myles Watson6bd442f2016-10-19 09:50:22 -070092 BTIF_HF_ID_1 = 0,
93 BTIF_HF_ID_2,
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070094#if (BTIF_HF_NUM_CB == 3)
Myles Watson6bd442f2016-10-19 09:50:22 -070095 BTIF_HF_ID_3
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -070096#endif
97} bthf_hf_id_t;
98
Marie Janssenb7f64bc2016-06-22 12:52:19 -070099uint16_t bthf_hf_id[BTIF_HF_NUM_CB] = {BTIF_HF_ID_1, BTIF_HF_ID_2,
Myles Watson6bd442f2016-10-19 09:50:22 -0700100#if (BTIF_HF_NUM_CB == 3)
101 BTIF_HF_ID_3
102#endif
103};
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700104
Myles Watsonee96a3c2016-11-23 14:49:54 -0800105/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700106 * Local type definitions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800107 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800108
Myles Watsonee96a3c2016-11-23 14:49:54 -0800109/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700110 * Static variables
Myles Watsonee96a3c2016-11-23 14:49:54 -0800111 ******************************************************************************/
Myles Watson6bd442f2016-10-19 09:50:22 -0700112static bthf_callbacks_t* bt_hf_callbacks = NULL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700113static int hf_idx = BTIF_HF_INVALID_IDX;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800114
Myles Watson40cde562016-10-21 09:39:13 -0700115#define CHECK_BTHF_INIT() \
116 do { \
117 if (bt_hf_callbacks == NULL) { \
118 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__); \
119 return BT_STATUS_NOT_READY; \
120 } else { \
121 BTIF_TRACE_EVENT("BTHF: %s", __func__); \
122 } \
123 } while (0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800124
The Android Open Source Project5738f832012-12-12 16:00:35 -0800125/* BTIF-HF control block to map bdaddr to BTA handle */
Myles Watson6bd442f2016-10-19 09:50:22 -0700126typedef struct _btif_hf_cb {
127 uint16_t handle;
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700128 RawAddress connected_bda;
Myles Watson6bd442f2016-10-19 09:50:22 -0700129 bthf_connection_state_t state;
130 bthf_vr_state_t vr_state;
131 tBTA_AG_PEER_FEAT peer_feat;
132 int num_active;
133 int num_held;
134 struct timespec call_end_timestamp;
135 struct timespec connected_timestamp;
136 bthf_call_state_t call_setup_state;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800137} btif_hf_cb_t;
138
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700139static btif_hf_cb_t btif_hf_cb[BTIF_HF_NUM_CB];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800140
Myles Watsonee96a3c2016-11-23 14:49:54 -0800141/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700142 * Static functions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800143 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800144
Myles Watsonee96a3c2016-11-23 14:49:54 -0800145/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700146 * Externs
Myles Watsonee96a3c2016-11-23 14:49:54 -0800147 ******************************************************************************/
Myles Watson6bd442f2016-10-19 09:50:22 -0700148/* By default, even though codec negotiation is enabled, we will not use WBS as
Jakub Pawlowski78b81c62017-06-16 13:55:52 -0700149 * the default
150 * codec unless this variable is set to true.
151 */
Matthew Xie66432dc2014-04-27 05:45:32 -0700152#ifndef BTIF_HF_WBS_PREFERRED
Myles Watson6bd442f2016-10-19 09:50:22 -0700153#define BTIF_HF_WBS_PREFERRED false
Matthew Xie66432dc2014-04-27 05:45:32 -0700154#endif
155
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700156bool btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800157
Myles Watsonee96a3c2016-11-23 14:49:54 -0800158/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700159 * Functions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800160 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800161
162/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700163 *
164 * Function is_connected
165 *
166 * Description Internal function to check if HF is connected
167 *
168 * Returns true if connected
169 *
170 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700171static bool is_connected(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700172 int i;
173 for (i = 0; i < btif_max_hf_clients; ++i) {
174 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
175 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)) &&
Jakub Pawlowski78b81c62017-06-16 13:55:52 -0700176 (!bd_addr || *bd_addr == btif_hf_cb[i].connected_bda))
Myles Watson6bd442f2016-10-19 09:50:22 -0700177 return true;
178 }
179 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800180}
181
182/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700183 *
184 * Function btif_hf_idx_by_bdaddr
185 *
186 * Description Internal function to get idx by bdaddr
187 *
188 * Returns idx
189 *
190 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700191static int btif_hf_idx_by_bdaddr(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700192 int i;
193 for (i = 0; i < btif_max_hf_clients; ++i) {
Jakub Pawlowski78b81c62017-06-16 13:55:52 -0700194 if (*bd_addr == btif_hf_cb[i].connected_bda) return i;
Myles Watson6bd442f2016-10-19 09:50:22 -0700195 }
196 return BTIF_HF_INVALID_IDX;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -0700197}
198
199/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700200 *
201 * Function callstate_to_callsetup
202 *
203 * Description Converts HAL call state to BTA call setup indicator value
204 *
205 * Returns BTA call indicator value
206 *
207 ******************************************************************************/
208static uint8_t callstate_to_callsetup(bthf_call_state_t call_state) {
209 uint8_t call_setup = 0;
210 if (call_state == BTHF_CALL_STATE_INCOMING) call_setup = 1;
211 if (call_state == BTHF_CALL_STATE_DIALING) call_setup = 2;
212 if (call_state == BTHF_CALL_STATE_ALERTING) call_setup = 3;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800213
Myles Watson6bd442f2016-10-19 09:50:22 -0700214 return call_setup;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800215}
216
217/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700218 *
219 * Function send_at_result
220 *
221 * Description Send AT result code (OK/ERROR)
222 *
223 * Returns void
224 *
225 ******************************************************************************/
226static void send_at_result(uint8_t ok_flag, uint16_t errcode, int idx) {
227 tBTA_AG_RES_DATA ag_res;
228 memset(&ag_res, 0, sizeof(ag_res));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800229
Myles Watson6bd442f2016-10-19 09:50:22 -0700230 ag_res.ok_flag = ok_flag;
231 if (ok_flag == BTA_AG_OK_ERROR) {
232 ag_res.errcode = errcode;
233 }
234
235 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
236}
237
238/*******************************************************************************
239 *
240 * Function send_indicator_update
241 *
242 * Description Send indicator update (CIEV)
243 *
244 * Returns void
245 *
246 ******************************************************************************/
247static void send_indicator_update(uint16_t indicator, uint16_t value) {
248 tBTA_AG_RES_DATA ag_res;
249
250 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
251 ag_res.ind.id = indicator;
252 ag_res.ind.value = value;
253
254 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_IND_RES, &ag_res);
255}
256
257void clear_phone_state_multihf(int idx) {
258 btif_hf_cb[idx].call_setup_state = BTHF_CALL_STATE_IDLE;
259 btif_hf_cb[idx].num_active = btif_hf_cb[idx].num_held = 0;
260}
261
262/*******************************************************************************
263 *
264 * Function btif_hf_latest_connected_idx
265 *
266 * Description Returns idx for latest connected HF
267 *
268 * Returns int
269 *
270 ******************************************************************************/
271static int btif_hf_latest_connected_idx() {
272 struct timespec now, conn_time_delta;
273 int latest_conn_idx = BTIF_HF_INVALID_IDX, i;
274
275 clock_gettime(CLOCK_MONOTONIC, &now);
276 conn_time_delta.tv_sec = now.tv_sec;
277
278 for (i = 0; i < btif_max_hf_clients; i++) {
279 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
280 if ((now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec) <
281 conn_time_delta.tv_sec) {
282 conn_time_delta.tv_sec =
283 now.tv_sec - btif_hf_cb[i].connected_timestamp.tv_sec;
284 latest_conn_idx = i;
285 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800286 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700287 }
288 return latest_conn_idx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800289}
290
291/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700292 *
293 * Function btif_hf_check_if_slc_connected
294 *
295 * Description Returns BT_STATUS_SUCCESS if SLC is up for any HF
296 *
297 * Returns bt_status_t
298 *
299 ******************************************************************************/
300static bt_status_t btif_hf_check_if_slc_connected() {
301 if (bt_hf_callbacks == NULL) {
302 BTIF_TRACE_WARNING("BTHF: %s: BTHF not initialized", __func__);
303 return BT_STATUS_NOT_READY;
304 } else {
305 int i;
306 for (i = 0; i < btif_max_hf_clients; i++) {
307 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
308 BTIF_TRACE_EVENT("BTHF: %s: slc connected for idx = %d", __func__, i);
309 return BT_STATUS_SUCCESS;
310 }
311 }
312 BTIF_TRACE_WARNING("BTHF: %s: No SLC connection up", __func__);
313 return BT_STATUS_NOT_READY;
314 }
315}
316
317/*****************************************************************************
318 * Section name (Group of functions)
319 ****************************************************************************/
320
321/*****************************************************************************
322 *
323 * btif hf api functions (no context switch)
324 *
325 ****************************************************************************/
326
327/*******************************************************************************
328 *
329 * Function btif_hf_upstreams_evt
330 *
331 * Description Executes HF UPSTREAMS events in btif context
332 *
333 * Returns void
334 *
335 ******************************************************************************/
336static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
337 tBTA_AG* p_data = (tBTA_AG*)p_param;
Myles Watson6bd442f2016-10-19 09:50:22 -0700338 int idx = p_data->hdr.handle - 1;
339
340 BTIF_TRACE_DEBUG("%s: event=%s", __func__, dump_hf_event(event));
341
342 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
343 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
344 return;
345 }
346
347 switch (event) {
348 case BTA_AG_ENABLE_EVT:
349 case BTA_AG_DISABLE_EVT:
350 break;
351
352 case BTA_AG_REGISTER_EVT:
353 btif_hf_cb[idx].handle = p_data->reg.hdr.handle;
354 BTIF_TRACE_DEBUG(
355 "%s: BTA_AG_REGISTER_EVT,"
356 "btif_hf_cb.handle = %d",
357 __func__, btif_hf_cb[idx].handle);
358 break;
359
360 case BTA_AG_OPEN_EVT:
361 if (p_data->open.status == BTA_AG_SUCCESS) {
Jakub Pawlowskia83ac122017-06-15 11:53:33 -0700362 btif_hf_cb[idx].connected_bda = p_data->open.bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -0700363 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
364 btif_hf_cb[idx].peer_feat = 0;
365 clear_phone_state_multihf(idx);
366 } else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING) {
367 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
368 } else {
369 BTIF_TRACE_WARNING(
370 "%s: AG open failed, but another device connected. status=%d "
371 "state=%d connected device=%s",
372 __func__, p_data->open.status, btif_hf_cb[idx].state,
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700373 btif_hf_cb[idx].connected_bda.ToString().c_str());
Myles Watson6bd442f2016-10-19 09:50:22 -0700374 break;
375 }
376
377 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
378 &btif_hf_cb[idx].connected_bda);
379
380 if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700381 btif_hf_cb[idx].connected_bda = RawAddress::kAny;
Myles Watson6bd442f2016-10-19 09:50:22 -0700382
383 if (p_data->open.status != BTA_AG_SUCCESS) btif_queue_advance();
384 break;
385
386 case BTA_AG_CLOSE_EVT:
387 btif_hf_cb[idx].connected_timestamp.tv_sec = 0;
388 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
389 BTIF_TRACE_DEBUG(
390 "%s: BTA_AG_CLOSE_EVT,"
391 "idx = %d, btif_hf_cb.handle = %d",
392 __func__, idx, btif_hf_cb[idx].handle);
393 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
394 &btif_hf_cb[idx].connected_bda);
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700395 btif_hf_cb[idx].connected_bda = RawAddress::kAny;
Myles Watson6bd442f2016-10-19 09:50:22 -0700396 btif_hf_cb[idx].peer_feat = 0;
397 clear_phone_state_multihf(idx);
398 hf_idx = btif_hf_latest_connected_idx();
399 /* If AG_OPEN was received but SLC was not setup in a specified time (10
Jakub Pawlowski78b81c62017-06-16 13:55:52 -0700400 *seconds),
401 ** then AG_CLOSE may be received. We need to advance the queue here
402 */
Myles Watson6bd442f2016-10-19 09:50:22 -0700403 btif_queue_advance();
404 break;
405
406 case BTA_AG_CONN_EVT:
407 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[idx].connected_timestamp);
408 BTIF_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ", __func__, idx);
409 btif_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
410 btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_SLC_CONNECTED;
411 hf_idx = btif_hf_latest_connected_idx();
412
413 HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
414 &btif_hf_cb[idx].connected_bda);
415 btif_queue_advance();
416 break;
417
418 case BTA_AG_AUDIO_OPEN_EVT:
419 hf_idx = idx;
420 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTED,
421 &btif_hf_cb[idx].connected_bda);
422 break;
423
424 case BTA_AG_AUDIO_CLOSE_EVT:
425 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_DISCONNECTED,
426 &btif_hf_cb[idx].connected_bda);
427 break;
428
429 /* BTA auto-responds, silently discard */
430 case BTA_AG_SPK_EVT:
431 case BTA_AG_MIC_EVT:
432 HAL_CBACK(bt_hf_callbacks, volume_cmd_cb,
433 (event == BTA_AG_SPK_EVT) ? BTHF_VOLUME_TYPE_SPK
434 : BTHF_VOLUME_TYPE_MIC,
435 p_data->val.num, &btif_hf_cb[idx].connected_bda);
436 break;
437
438 case BTA_AG_AT_A_EVT:
439 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
440 hf_idx = idx;
441 else
442 BTIF_TRACE_DEBUG("Donot set hf_idx for ATA since already in a call");
443
444 HAL_CBACK(bt_hf_callbacks, answer_call_cmd_cb,
445 &btif_hf_cb[idx].connected_bda);
446 break;
447
448 /* Java needs to send OK/ERROR for these commands */
449 case BTA_AG_AT_BLDN_EVT:
450 case BTA_AG_AT_D_EVT:
451 if ((btif_hf_cb[0].num_held + btif_hf_cb[0].num_active) == 0)
452 hf_idx = idx;
453 else
454 BTIF_TRACE_DEBUG("Donot set hf_idx for BLDN/D since already in a call");
455
456 HAL_CBACK(bt_hf_callbacks, dial_call_cmd_cb,
457 (event == BTA_AG_AT_D_EVT) ? p_data->val.str : NULL,
458 &btif_hf_cb[idx].connected_bda);
459 break;
460
461 case BTA_AG_AT_CHUP_EVT:
462 HAL_CBACK(bt_hf_callbacks, hangup_call_cmd_cb,
463 &btif_hf_cb[idx].connected_bda);
464 break;
465
466 case BTA_AG_AT_CIND_EVT:
467 HAL_CBACK(bt_hf_callbacks, cind_cmd_cb, &btif_hf_cb[idx].connected_bda);
468 break;
469
470 case BTA_AG_AT_VTS_EVT:
471 HAL_CBACK(bt_hf_callbacks, dtmf_cmd_cb, p_data->val.str[0],
472 &btif_hf_cb[idx].connected_bda);
473 break;
474
475 case BTA_AG_AT_BVRA_EVT:
476 HAL_CBACK(bt_hf_callbacks, vr_cmd_cb,
477 (p_data->val.num == 1) ? BTHF_VR_STATE_STARTED
478 : BTHF_VR_STATE_STOPPED,
479 &btif_hf_cb[idx].connected_bda);
480 break;
481
482 case BTA_AG_AT_NREC_EVT:
483 HAL_CBACK(bt_hf_callbacks, nrec_cmd_cb,
484 (p_data->val.num == 1) ? BTHF_NREC_START : BTHF_NREC_STOP,
485 &btif_hf_cb[idx].connected_bda);
486 break;
487
488 /* TODO: Add a callback for CBC */
489 case BTA_AG_AT_CBC_EVT:
490 break;
491
492 case BTA_AG_AT_CKPD_EVT:
493 HAL_CBACK(bt_hf_callbacks, key_pressed_cmd_cb,
494 &btif_hf_cb[idx].connected_bda);
495 break;
496
Myles Watson6bd442f2016-10-19 09:50:22 -0700497 case BTA_AG_WBS_EVT:
498 BTIF_TRACE_DEBUG(
499 "BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC",
500 p_data->val.hdr.status, p_data->val.num);
501 if (p_data->val.num == BTA_AG_CODEC_CVSD) {
502 HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NO,
503 &btif_hf_cb[idx].connected_bda);
504 } else if (p_data->val.num == BTA_AG_CODEC_MSBC) {
505 HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_YES,
506 &btif_hf_cb[idx].connected_bda);
507 } else {
508 HAL_CBACK(bt_hf_callbacks, wbs_cb, BTHF_WBS_NONE,
509 &btif_hf_cb[idx].connected_bda);
510 }
511 break;
Myles Watson3e634d62017-02-09 16:26:34 -0800512
Myles Watson6bd442f2016-10-19 09:50:22 -0700513 /* Java needs to send OK/ERROR for these commands */
514 case BTA_AG_AT_CHLD_EVT:
515 HAL_CBACK(bt_hf_callbacks, chld_cmd_cb,
516 (bthf_chld_type_t)atoi(p_data->val.str),
517 &btif_hf_cb[idx].connected_bda);
518 break;
519
520 case BTA_AG_AT_CLCC_EVT:
521 HAL_CBACK(bt_hf_callbacks, clcc_cmd_cb, &btif_hf_cb[idx].connected_bda);
522 break;
523
524 case BTA_AG_AT_COPS_EVT:
525 HAL_CBACK(bt_hf_callbacks, cops_cmd_cb, &btif_hf_cb[idx].connected_bda);
526 break;
527
528 case BTA_AG_AT_UNAT_EVT:
529 HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str,
530 &btif_hf_cb[idx].connected_bda);
531 break;
532
533 case BTA_AG_AT_CNUM_EVT:
534 HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb, &btif_hf_cb[idx].connected_bda);
535 break;
536
537 /* TODO: Some of these commands may need to be sent to app. For now respond
538 * with error */
539 case BTA_AG_AT_BINP_EVT:
540 case BTA_AG_AT_BTRH_EVT:
541 send_at_result(BTA_AG_OK_ERROR, BTA_AG_ERR_OP_NOT_SUPPORTED, idx);
542 break;
543 case BTA_AG_AT_BAC_EVT:
544 BTIF_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num);
Jack Hefe695a52017-05-07 17:27:47 -0700545 /* If the peer supports mSBC and the BTIF preferred codec is also mSBC,
Myles Watson6bd442f2016-10-19 09:50:22 -0700546 then
547 we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC
548 at the time
549 of SCO connection establishment */
Myles Watsonb749ebd2017-10-06 16:39:05 -0700550 if ((btif_conf_hf_force_wbs) && (p_data->val.num & BTA_AG_CODEC_MSBC)) {
Jack Hefe695a52017-05-07 17:27:47 -0700551 BTIF_TRACE_EVENT("%s: btif_hf override-Preferred Codec to MSBC",
Myles Watson6bd442f2016-10-19 09:50:22 -0700552 __func__);
553 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
554 } else {
555 BTIF_TRACE_EVENT("%s btif_hf override-Preferred Codec to CVSD",
556 __func__);
557 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_CVSD);
558 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700559 break;
560 case BTA_AG_AT_BCS_EVT:
Jack Hefe695a52017-05-07 17:27:47 -0700561 BTIF_TRACE_DEBUG("%s: AG final selected codec is 0x%02x 1=CVSD 2=MSBC",
562 __func__, p_data->val.num);
563 /* No BTHF_WBS_NONE case, because HF1.6 supported device can send BCS */
564 /* Only CVSD is considered narrow band speech */
Myles Watson6bd442f2016-10-19 09:50:22 -0700565 HAL_CBACK(
566 bt_hf_callbacks, wbs_cb,
Jack Hefe695a52017-05-07 17:27:47 -0700567 (p_data->val.num == BTA_AG_CODEC_CVSD) ? BTHF_WBS_NO : BTHF_WBS_YES,
Myles Watson6bd442f2016-10-19 09:50:22 -0700568 &btif_hf_cb[idx].connected_bda);
569 break;
570
571 case BTA_AG_AT_BIND_EVT:
572 if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
573 HAL_CBACK(bt_hf_callbacks, bind_cb, p_data->val.str,
574 &btif_hf_cb[idx].connected_bda);
575 }
576 break;
577
578 case BTA_AG_AT_BIEV_EVT:
579 if (p_data->val.hdr.status == BTA_AG_SUCCESS) {
580 HAL_CBACK(bt_hf_callbacks, biev_cb,
581 (bthf_hf_ind_type_t)p_data->val.lidx, (int)p_data->val.num,
582 &btif_hf_cb[idx].connected_bda);
583 }
584 break;
585 default:
586 BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
587 break;
588 }
589}
590
591/*******************************************************************************
592 *
593 * Function bte_hf_evt
594 *
595 * Description Switches context from BTE to BTIF for all HF events
596 *
597 * Returns void
598 *
599 ******************************************************************************/
600
601static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG* p_data) {
602 bt_status_t status;
603 int param_len = 0;
604
605 /* TODO: BTA sends the union members and not tBTA_AG. If using
606 * param_len=sizeof(tBTA_AG), we get a crash on memcpy */
607 if (BTA_AG_REGISTER_EVT == event)
608 param_len = sizeof(tBTA_AG_REGISTER);
609 else if (BTA_AG_OPEN_EVT == event)
610 param_len = sizeof(tBTA_AG_OPEN);
611 else if (BTA_AG_CONN_EVT == event)
612 param_len = sizeof(tBTA_AG_CONN);
613 else if ((BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) ||
614 (BTA_AG_AUDIO_CLOSE_EVT == event))
615 param_len = sizeof(tBTA_AG_HDR);
616 else if (p_data)
617 param_len = sizeof(tBTA_AG_VAL);
618
619 /* switch context to btif task context (copy full union size for convenience)
620 */
621 status = btif_transfer_context(btif_hf_upstreams_evt, (uint16_t)event,
622 (char*)p_data, param_len, NULL);
623
624 /* catch any failed context transfers */
625 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
626}
627
628/*******************************************************************************
629 *
630 * Function btif_in_hf_generic_evt
631 *
632 * Description Processes generic events to be sent to JNI that are not
Myles Watsonf4548162016-10-19 09:53:56 -0700633 * triggered from the BTA.
Myles Watson6bd442f2016-10-19 09:50:22 -0700634 * Always runs in BTIF context
635 *
636 * Returns void
637 *
638 ******************************************************************************/
639static void btif_in_hf_generic_evt(uint16_t event, char* p_param) {
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700640 int idx = btif_hf_idx_by_bdaddr((RawAddress*)p_param);
Myles Watson6bd442f2016-10-19 09:50:22 -0700641
642 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
643
644 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
645 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
646 return;
647 }
648
649 switch (event) {
650 case BTIF_HFP_CB_AUDIO_CONNECTING: {
651 HAL_CBACK(bt_hf_callbacks, audio_state_cb, BTHF_AUDIO_STATE_CONNECTING,
652 &btif_hf_cb[idx].connected_bda);
653 } break;
654 default: {
655 BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
656 } break;
657 }
658}
659
Jack He7a9892c2017-02-02 17:42:40 -0800660static bool inband_ringing_property_enabled() {
661 char inband_ringing_flag[PROPERTY_VALUE_MAX] = {0};
662 osi_property_get("persist.bluetooth.enableinbandringing", inband_ringing_flag,
663 "false");
664 if (strncmp(inband_ringing_flag, "true", 4) == 0) {
665 BTIF_TRACE_DEBUG("%s: In-band ringing enabled by property", __func__);
666 return true;
667 }
668 return false;
669}
670
Myles Watson6bd442f2016-10-19 09:50:22 -0700671/*******************************************************************************
672 *
673 * Function btif_hf_init
674 *
675 * Description initializes the hf interface
676 *
677 * Returns bt_status_t
678 *
679 ******************************************************************************/
Jack He7a9892c2017-02-02 17:42:40 -0800680static bt_status_t init(bthf_callbacks_t* callbacks, int max_hf_clients,
681 bool inband_ringing_supported) {
682 bool inband_ringing_property_enable = inband_ringing_property_enabled();
683 if (inband_ringing_supported && inband_ringing_property_enable) {
684 btif_hf_features |= BTA_AG_FEAT_INBAND;
685 } else {
686 btif_hf_features &= ~BTA_AG_FEAT_INBAND;
687 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700688 btif_max_hf_clients = max_hf_clients;
Jack He7a9892c2017-02-02 17:42:40 -0800689 BTIF_TRACE_DEBUG(
690 "%s: btif_hf_features=%zu, max_hf_clients=%d, "
691 "inband_ringing=[supported=%d, enabled=%d]",
692 __func__, btif_hf_features, btif_max_hf_clients, inband_ringing_supported,
693 inband_ringing_property_enable);
Myles Watson6bd442f2016-10-19 09:50:22 -0700694 bt_hf_callbacks = callbacks;
695 memset(&btif_hf_cb, 0, sizeof(btif_hf_cb));
696
697/* Invoke the enable service API to the core to set the appropriate service_id
698 * Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled
699 * (phone)
700 * othwerwise only HSP is enabled (tablet)
Jakub Pawlowski78b81c62017-06-16 13:55:52 -0700701 */
Myles Watson6bd442f2016-10-19 09:50:22 -0700702#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
703 btif_enable_service(BTA_HFP_SERVICE_ID);
704#else
705 btif_enable_service(BTA_HSP_SERVICE_ID);
706#endif
707
708 for (int i = 0; i < btif_max_hf_clients; i++) clear_phone_state_multihf(i);
709
710 return BT_STATUS_SUCCESS;
711}
712
713/*******************************************************************************
714 *
715 * Function connect
716 *
717 * Description connect to headset
718 *
719 * Returns bt_status_t
720 *
721 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700722static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700723 CHECK_BTHF_INIT();
724 int i;
725 for (i = 0; i < btif_max_hf_clients;) {
726 if (((btif_hf_cb[i].state == BTHF_CONNECTION_STATE_CONNECTED) ||
727 (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED)))
728 i++;
729 else
730 break;
731 }
732
733 if (i == btif_max_hf_clients) return BT_STATUS_BUSY;
734
735 if (!is_connected(bd_addr)) {
736 btif_hf_cb[i].state = BTHF_CONNECTION_STATE_CONNECTING;
Jakub Pawlowskia83ac122017-06-15 11:53:33 -0700737 btif_hf_cb[i].connected_bda = *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -0700738
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700739 BTA_AgOpen(btif_hf_cb[i].handle, btif_hf_cb[i].connected_bda,
Myles Watson6bd442f2016-10-19 09:50:22 -0700740 BTIF_HF_SECURITY, BTIF_HF_SERVICES);
741 return BT_STATUS_SUCCESS;
742 }
743
744 return BT_STATUS_BUSY;
745}
746
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700747static bt_status_t connect(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700748 CHECK_BTHF_INIT();
749 return btif_queue_connect(UUID_SERVCLASS_AG_HANDSFREE, bd_addr, connect_int);
750}
751
752/*******************************************************************************
753 *
754 * Function disconnect
755 *
756 * Description disconnect from headset
757 *
758 * Returns bt_status_t
759 *
760 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700761static bt_status_t disconnect(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700762 CHECK_BTHF_INIT();
763
764 int idx = btif_hf_idx_by_bdaddr(bd_addr);
765
766 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
767 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
768 return BT_STATUS_FAIL;
769 }
770
771 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
772 BTA_AgClose(btif_hf_cb[idx].handle);
773 return BT_STATUS_SUCCESS;
774 }
775
776 return BT_STATUS_FAIL;
777}
778
779/*******************************************************************************
780 *
781 * Function connect_audio
782 *
783 * Description create an audio connection
784 *
785 * Returns bt_status_t
786 *
787 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700788static bt_status_t connect_audio(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700789 CHECK_BTHF_INIT();
790
791 int idx = btif_hf_idx_by_bdaddr(bd_addr);
792
793 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
794 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
795 return BT_STATUS_FAIL;
796 }
797
798 /* Check if SLC is connected */
799 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
800 return BT_STATUS_NOT_READY;
801
802 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
803 BTA_AgAudioOpen(btif_hf_cb[idx].handle);
804
805 /* Inform the application that the audio connection has been initiated
806 * successfully */
807 btif_transfer_context(btif_in_hf_generic_evt, BTIF_HFP_CB_AUDIO_CONNECTING,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700808 (char*)bd_addr, sizeof(RawAddress), NULL);
Myles Watson6bd442f2016-10-19 09:50:22 -0700809 return BT_STATUS_SUCCESS;
810 }
811
812 return BT_STATUS_FAIL;
813}
814
815/*******************************************************************************
816 *
817 * Function disconnect_audio
818 *
819 * Description close the audio connection
820 *
821 * Returns bt_status_t
822 *
823 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700824static bt_status_t disconnect_audio(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700825 CHECK_BTHF_INIT();
826
827 int idx = btif_hf_idx_by_bdaddr(bd_addr);
828
829 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
830 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
831 return BT_STATUS_FAIL;
832 }
833
834 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
835 BTA_AgAudioClose(btif_hf_cb[idx].handle);
836 return BT_STATUS_SUCCESS;
837 }
838
839 return BT_STATUS_FAIL;
840}
841
842/*******************************************************************************
843 *
844 * Function start_voice_recognition
845 *
846 * Description start voice recognition
847 *
848 * Returns bt_status_t
849 *
850 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700851static bt_status_t start_voice_recognition(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700852 CHECK_BTHF_INIT();
853
854 int idx = btif_hf_idx_by_bdaddr(bd_addr);
855
856 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
857 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
858 return BT_STATUS_FAIL;
859 }
860
861 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
862 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
863 tBTA_AG_RES_DATA ag_res;
864 memset(&ag_res, 0, sizeof(ag_res));
865 ag_res.state = 1;
866 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
867
868 return BT_STATUS_SUCCESS;
869 } else {
870 return BT_STATUS_UNSUPPORTED;
871 }
872 }
873
874 return BT_STATUS_NOT_READY;
875}
876
877/*******************************************************************************
878 *
879 * Function stop_voice_recognition
880 *
881 * Description stop voice recognition
882 *
883 * Returns bt_status_t
884 *
885 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700886static bt_status_t stop_voice_recognition(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700887 CHECK_BTHF_INIT();
888
889 int idx = btif_hf_idx_by_bdaddr(bd_addr);
890
891 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
892 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
893 return BT_STATUS_FAIL;
894 }
895
896 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
897 if (btif_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
898 tBTA_AG_RES_DATA ag_res;
899 memset(&ag_res, 0, sizeof(ag_res));
900 ag_res.state = 0;
901 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
902
903 return BT_STATUS_SUCCESS;
904 } else {
905 return BT_STATUS_UNSUPPORTED;
906 }
907 }
908
909 return BT_STATUS_NOT_READY;
910}
911
912/*******************************************************************************
913 *
914 * Function volume_control
915 *
916 * Description volume control
917 *
918 * Returns bt_status_t
919 *
920 ******************************************************************************/
921static bt_status_t volume_control(bthf_volume_type_t type, int volume,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700922 RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700923 CHECK_BTHF_INIT();
924
925 int idx = btif_hf_idx_by_bdaddr(bd_addr);
926
927 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
928 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
929 return BT_STATUS_FAIL;
930 }
931
932 tBTA_AG_RES_DATA ag_res;
933 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
934 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
935 ag_res.num = volume;
936 BTA_AgResult(
937 btif_hf_cb[idx].handle,
938 (type == BTHF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES,
939 &ag_res);
940 return BT_STATUS_SUCCESS;
941 }
942
943 return BT_STATUS_FAIL;
944}
945
946/*******************************************************************************
947 *
948 * Function device_status_notification
949 *
950 * Description Combined device status change notification
951 *
952 * Returns bt_status_t
953 *
954 ******************************************************************************/
955static bt_status_t device_status_notification(bthf_network_state_t ntk_state,
956 bthf_service_type_t svc_type,
957 int signal, int batt_chg) {
958 CHECK_BTHF_INIT();
959
960 if (is_connected(NULL)) {
961 /* send all indicators to BTA.
962 ** BTA will make sure no duplicates are sent out
963 */
964 send_indicator_update(BTA_AG_IND_SERVICE,
965 (ntk_state == BTHF_NETWORK_STATE_AVAILABLE) ? 1 : 0);
966 send_indicator_update(BTA_AG_IND_ROAM,
967 (svc_type == BTHF_SERVICE_TYPE_HOME) ? 0 : 1);
968 send_indicator_update(BTA_AG_IND_SIGNAL, signal);
969 send_indicator_update(BTA_AG_IND_BATTCHG, batt_chg);
970 return BT_STATUS_SUCCESS;
971 }
972
973 return BT_STATUS_SUCCESS;
974}
975
976/*******************************************************************************
977 *
978 * Function cops_response
979 *
980 * Description Response for COPS command
981 *
982 * Returns bt_status_t
983 *
984 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700985static bt_status_t cops_response(const char* cops, RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700986 CHECK_BTHF_INIT();
987
988 int idx = btif_hf_idx_by_bdaddr(bd_addr);
989
990 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
991 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
992 return BT_STATUS_FAIL;
993 }
994
995 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800996 tBTA_AG_RES_DATA ag_res;
997
Myles Watson6bd442f2016-10-19 09:50:22 -0700998 /* Format the response */
999 snprintf(ag_res.str, sizeof(ag_res.str), "0,0,\"%.16s\"", cops);
1000 ag_res.ok_flag = BTA_AG_OK_DONE;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001001
Myles Watson6bd442f2016-10-19 09:50:22 -07001002 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
1003 return BT_STATUS_SUCCESS;
1004 }
1005 return BT_STATUS_FAIL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001006}
1007
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001008/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001009 *
1010 * Function cind_response
1011 *
1012 * Description Response for CIND command
1013 *
1014 * Returns bt_status_t
1015 *
1016 ******************************************************************************/
1017static bt_status_t cind_response(int svc, int num_active, int num_held,
1018 bthf_call_state_t call_setup_state, int signal,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001019 int roam, int batt_chg, RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001020 CHECK_BTHF_INIT();
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001021
Myles Watson6bd442f2016-10-19 09:50:22 -07001022 int idx = btif_hf_idx_by_bdaddr(bd_addr);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001023
Myles Watson6bd442f2016-10-19 09:50:22 -07001024 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1025 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1026 return BT_STATUS_FAIL;
1027 }
1028
1029 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1030 tBTA_AG_RES_DATA ag_res;
1031
1032 memset(&ag_res, 0, sizeof(ag_res));
1033 /* per the errata 2043, call=1 implies atleast one call is in progress
Jakub Pawlowski78b81c62017-06-16 13:55:52 -07001034 *(active/held)
1035 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1036 **/
Myles Watson6bd442f2016-10-19 09:50:22 -07001037 snprintf(
1038 ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d,%d,%d",
1039 (num_active + num_held) ? 1 : 0, /* Call state */
1040 callstate_to_callsetup(call_setup_state), /* Callsetup state */
1041 svc, /* network service */
1042 signal, /* Signal strength */
1043 roam, /* Roaming indicator */
1044 batt_chg, /* Battery level */
1045 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1))); /* Call held */
1046
1047 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
1048
1049 return BT_STATUS_SUCCESS;
1050 }
1051
1052 return BT_STATUS_FAIL;
1053}
1054
1055/*******************************************************************************
1056 *
1057 * Function bind_response
1058 *
1059 * Description Send +BIND response
1060 *
1061 * Returns bt_status_t
1062 *
1063 ******************************************************************************/
1064static bt_status_t bind_response(bthf_hf_ind_type_t ind_id,
1065 bthf_hf_ind_status_t ind_status,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001066 RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001067 CHECK_BTHF_INIT();
1068
1069 int index = btif_hf_idx_by_bdaddr(bd_addr);
1070 if (!is_connected(bd_addr) || index == BTIF_HF_INVALID_IDX)
1071 return BT_STATUS_FAIL;
1072
1073 tBTA_AG_RES_DATA ag_res;
1074 memset(&ag_res, 0, sizeof(ag_res));
1075 ag_res.ind.id = ind_id;
1076 ag_res.ind.on_demand = (ind_status == BTHF_HF_IND_ENABLED);
1077
1078 BTA_AgResult(btif_hf_cb[index].handle, BTA_AG_BIND_RES, &ag_res);
1079 return BT_STATUS_SUCCESS;
1080}
1081
Zach Johnsonacdc11c2017-04-18 21:03:07 -07001082static bt_status_t set_sco_allowed(bool value) {
1083 CHECK_BTHF_INIT();
1084
1085 BTA_AgSetScoAllowed(value);
1086 return BT_STATUS_SUCCESS;
1087}
1088
Myles Watson6bd442f2016-10-19 09:50:22 -07001089/*******************************************************************************
1090 *
1091 * Function formatted_at_response
1092 *
1093 * Description Pre-formatted AT response, typically in response to unknown
Myles Watsonf4548162016-10-19 09:53:56 -07001094 * AT cmd
Myles Watson6bd442f2016-10-19 09:50:22 -07001095 *
1096 * Returns bt_status_t
1097 *
1098 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001099static bt_status_t formatted_at_response(const char* rsp, RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001100 CHECK_BTHF_INIT();
1101 tBTA_AG_RES_DATA ag_res;
1102 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1103
1104 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1105 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1106 return BT_STATUS_FAIL;
1107 }
1108
1109 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1110 /* Format the response and send */
1111 memset(&ag_res, 0, sizeof(ag_res));
1112 strncpy(ag_res.str, rsp, BTA_AG_AT_MAX_LEN);
1113 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
1114
1115 return BT_STATUS_SUCCESS;
1116 }
1117
1118 return BT_STATUS_FAIL;
1119}
1120
1121/*******************************************************************************
1122 *
1123 * Function at_response
1124 *
1125 * Description ok/error response
1126 *
1127 * Returns bt_status_t
1128 *
1129 ******************************************************************************/
1130static bt_status_t at_response(bthf_at_response_t response_code, int error_code,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001131 RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001132 CHECK_BTHF_INIT();
1133
1134 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1135
1136 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1137 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1138 return BT_STATUS_FAIL;
1139 }
1140
1141 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1142 send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
1143 : BTA_AG_OK_ERROR,
1144 error_code, idx);
1145 return BT_STATUS_SUCCESS;
1146 }
1147
1148 return BT_STATUS_FAIL;
1149}
1150
1151/*******************************************************************************
1152 *
1153 * Function clcc_response
1154 *
1155 * Description response for CLCC command
1156 * Can be iteratively called for each call index. Call index
1157 * of 0 will be treated as NULL termination (Completes
Myles Watsonf4548162016-10-19 09:53:56 -07001158 * response)
Myles Watson6bd442f2016-10-19 09:50:22 -07001159 *
1160 * Returns bt_status_t
1161 *
1162 ******************************************************************************/
1163static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
1164 bthf_call_state_t state, bthf_call_mode_t mode,
1165 bthf_call_mpty_type_t mpty, const char* number,
1166 bthf_call_addrtype_t type,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001167 RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001168 CHECK_BTHF_INIT();
1169
1170 int idx = btif_hf_idx_by_bdaddr(bd_addr);
1171
1172 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1173 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1174 return BT_STATUS_FAIL;
1175 }
1176
1177 if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX)) {
1178 tBTA_AG_RES_DATA ag_res;
Myles Watson6bd442f2016-10-19 09:50:22 -07001179 memset(&ag_res, 0, sizeof(ag_res));
1180
1181 /* Format the response */
1182 if (index == 0) {
1183 ag_res.ok_flag = BTA_AG_OK_DONE;
1184 } else {
1185 BTIF_TRACE_EVENT(
1186 "clcc_response: [%d] dir %d state %d mode %d number = %s type = %d",
1187 index, dir, state, mode, number, type);
Myles Watson90088882016-11-15 16:33:22 -08001188 int res_strlen =
1189 snprintf(ag_res.str, sizeof(ag_res.str), "%d,%d,%d,%d,%d", index, dir,
1190 state, mode, mpty);
Myles Watson6bd442f2016-10-19 09:50:22 -07001191
1192 if (number) {
Satish Kodishalac75a71d2016-06-22 14:22:41 +05301193 size_t rem_bytes = sizeof(ag_res.str) - res_strlen;
1194 char dialnum[sizeof(ag_res.str)];
1195 size_t newidx = 0;
1196 if (type == BTHF_CALL_ADDRTYPE_INTERNATIONAL && *number != '+') {
1197 dialnum[newidx++] = '+';
1198 }
1199 for (size_t i = 0; number[i] != 0; i++) {
1200 if (utl_isdialchar(number[i])) {
1201 dialnum[newidx++] = number[i];
1202 }
1203 }
1204 dialnum[newidx] = 0;
1205 snprintf(&ag_res.str[res_strlen], rem_bytes, ",\"%s\",%d", dialnum,
1206 type);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001207 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001208 }
1209 BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
1210
1211 return BT_STATUS_SUCCESS;
1212 }
1213
1214 return BT_STATUS_FAIL;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001215}
1216
1217/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001218 *
1219 * Function phone_state_change
1220 *
1221 * Description notify of a call state change
1222 * number & type: valid only for incoming & waiting call
1223 *
1224 * Returns bt_status_t
1225 *
1226 ******************************************************************************/
1227
1228static bt_status_t phone_state_change(int num_active, int num_held,
1229 bthf_call_state_t call_setup_state,
1230 const char* number,
1231 bthf_call_addrtype_t type) {
1232 tBTA_AG_RES res = 0xff;
1233 tBTA_AG_RES_DATA ag_res;
1234 bt_status_t status = BT_STATUS_SUCCESS;
1235 bool activeCallUpdated = false;
1236 int idx, i;
1237
1238 /* hf_idx is index of connected HS that sent ATA/BLDN,
1239 otherwise index of latest connected HS */
1240 if (hf_idx != BTIF_HF_INVALID_IDX)
1241 idx = hf_idx;
1242 else
1243 idx = btif_hf_latest_connected_idx();
1244
1245 BTIF_TRACE_DEBUG("phone_state_change: idx = %d", idx);
1246
1247 /* Check if SLC is connected */
1248 if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
1249 return BT_STATUS_NOT_READY;
1250
1251 BTIF_TRACE_DEBUG(
1252 "phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d]"
1253 " call_setup=%s [prev: %s]",
1254 num_active, btif_hf_cb[idx].num_active, num_held,
1255 btif_hf_cb[idx].num_held, dump_hf_call_state(call_setup_state),
1256 dump_hf_call_state(btif_hf_cb[idx].call_setup_state));
1257
1258 /* if all indicators are 0, send end call and return */
1259 if (num_active == 0 && num_held == 0 &&
1260 call_setup_state == BTHF_CALL_STATE_IDLE) {
1261 BTIF_TRACE_DEBUG("%s: Phone on hook", __func__);
1262
1263 /* record call termination timestamp if there was an active/held call or
1264 callsetup state > BTHF_CALL_STATE_IDLE */
1265 if ((btif_hf_cb[idx].call_setup_state != BTHF_CALL_STATE_IDLE) ||
1266 (btif_hf_cb[idx].num_active) || (btif_hf_cb[idx].num_held)) {
1267 BTIF_TRACE_DEBUG("%s: Record call termination timestamp", __func__);
1268 clock_gettime(CLOCK_MONOTONIC, &btif_hf_cb[0].call_end_timestamp);
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001269 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001270 BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
1271 hf_idx = BTIF_HF_INVALID_IDX;
1272
1273 /* if held call was present, reset that as well */
1274 if (btif_hf_cb[idx].num_held) send_indicator_update(BTA_AG_IND_CALLHELD, 0);
1275
1276 goto update_call_states;
1277 }
1278
1279 /* active state can change when:
1280 ** 1. an outgoing/incoming call was answered
1281 ** 2. an held was resumed
1282 ** 3. without callsetup notifications, call became active
1283 ** (3) can happen if call is active and a headset connects to us
1284 **
1285 ** In the case of (3), we will have to notify the stack of an active
1286 ** call, instead of sending an indicator update. This will also
1287 ** force the SCO to be setup. Handle this special case here prior to
1288 ** call setup handling
1289 */
1290 if (((num_active + num_held) > 0) && (btif_hf_cb[idx].num_active == 0) &&
1291 (btif_hf_cb[idx].num_held == 0) &&
1292 (btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE)) {
1293 BTIF_TRACE_DEBUG(
1294 "%s: Active/Held call notification received without call setup update",
1295 __func__);
1296
1297 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1298 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
1299 /* Addition call setup with the Active call
1300 ** CIND response should have been updated.
Jack Hefe695a52017-05-07 17:27:47 -07001301 ** just open SCO connection.
Myles Watson6bd442f2016-10-19 09:50:22 -07001302 */
1303 if (call_setup_state != BTHF_CALL_STATE_IDLE)
1304 res = BTA_AG_MULTI_CALL_RES;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001305 else
Myles Watson6bd442f2016-10-19 09:50:22 -07001306 res = BTA_AG_OUT_CALL_CONN_RES;
1307 BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
1308 activeCallUpdated = true;
1309 }
1310
1311 /* Ringing call changed? */
1312 if (call_setup_state != btif_hf_cb[idx].call_setup_state) {
1313 BTIF_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s", __func__,
1314 dump_hf_call_state(btif_hf_cb[idx].call_setup_state),
1315 dump_hf_call_state(call_setup_state));
1316 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1317
1318 switch (call_setup_state) {
1319 case BTHF_CALL_STATE_IDLE: {
1320 switch (btif_hf_cb[idx].call_setup_state) {
1321 case BTHF_CALL_STATE_INCOMING:
1322 if (num_active > btif_hf_cb[idx].num_active) {
1323 res = BTA_AG_IN_CALL_CONN_RES;
1324 ag_res.audio_handle = btif_hf_cb[idx].handle;
1325 } else if (num_held > btif_hf_cb[idx].num_held)
1326 res = BTA_AG_IN_CALL_HELD_RES;
1327 else
1328 res = BTA_AG_CALL_CANCEL_RES;
1329 break;
1330 case BTHF_CALL_STATE_DIALING:
1331 case BTHF_CALL_STATE_ALERTING:
1332 if (num_active > btif_hf_cb[idx].num_active) {
1333 ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
1334 res = BTA_AG_OUT_CALL_CONN_RES;
1335 } else
1336 res = BTA_AG_CALL_CANCEL_RES;
1337 break;
1338 default:
1339 BTIF_TRACE_ERROR("%s: Incorrect Call setup state transition",
1340 __func__);
1341 status = BT_STATUS_PARM_INVALID;
1342 break;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001343 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001344 } break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001345
Myles Watson6bd442f2016-10-19 09:50:22 -07001346 case BTHF_CALL_STATE_INCOMING:
Jack He7a9892c2017-02-02 17:42:40 -08001347 if (num_active || num_held) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001348 res = BTA_AG_CALL_WAIT_RES;
Jack He7a9892c2017-02-02 17:42:40 -08001349 } else {
Myles Watson6bd442f2016-10-19 09:50:22 -07001350 res = BTA_AG_IN_CALL_RES;
Jack He7a9892c2017-02-02 17:42:40 -08001351 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001352 if (number) {
1353 int xx = 0;
1354 if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
1355 xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"+%s\"", number);
1356 else
1357 xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"%s\"", number);
1358 ag_res.num = type;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001359
Myles Watson6bd442f2016-10-19 09:50:22 -07001360 if (res == BTA_AG_CALL_WAIT_RES)
1361 snprintf(&ag_res.str[xx], sizeof(ag_res.str) - xx, ",%d", type);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001362 }
1363 break;
Myles Watson6bd442f2016-10-19 09:50:22 -07001364 case BTHF_CALL_STATE_DIALING:
1365 if (!(num_active + num_held))
1366 ag_res.audio_handle = btif_hf_cb[idx].handle;
1367 res = BTA_AG_OUT_CALL_ORIG_RES;
1368 break;
1369 case BTHF_CALL_STATE_ALERTING:
1370 /* if we went from idle->alert, force SCO setup here. dialing usually
1371 * triggers it */
1372 if ((btif_hf_cb[idx].call_setup_state == BTHF_CALL_STATE_IDLE) &&
1373 !(num_active + num_held))
1374 ag_res.audio_handle = btif_hf_cb[idx].handle;
1375 res = BTA_AG_OUT_CALL_ALERT_RES;
1376 break;
1377 default:
1378 BTIF_TRACE_ERROR("%s: Incorrect new ringing call state", __func__);
1379 status = BT_STATUS_PARM_INVALID;
1380 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001381 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001382 BTIF_TRACE_DEBUG("%s: Call setup state changed. res=%d, audio_handle=%d",
1383 __func__, res, ag_res.audio_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001384
Myles Watson6bd442f2016-10-19 09:50:22 -07001385 if (res) BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001386
Myles Watson6bd442f2016-10-19 09:50:22 -07001387 /* if call setup is idle, we have already updated call indicator, jump out
1388 */
1389 if (call_setup_state == BTHF_CALL_STATE_IDLE) {
1390 /* check & update callheld */
1391 if ((num_held > 0) && (num_active > 0))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001392 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
Myles Watson6bd442f2016-10-19 09:50:22 -07001393 goto update_call_states;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001394 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001395 }
1396
1397 memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
1398
1399 /* per the errata 2043, call=1 implies atleast one call is in progress
Jakub Pawlowski78b81c62017-06-16 13:55:52 -07001400 *(active/held)
1401 ** https://www.bluetooth.org/errata/errata_view.cfm?errata_id=2043
1402 ** Handle call indicator change
1403 **/
Myles Watson6bd442f2016-10-19 09:50:22 -07001404 if (!activeCallUpdated &&
1405 ((num_active + num_held) !=
1406 (btif_hf_cb[idx].num_active + btif_hf_cb[idx].num_held))) {
1407 BTIF_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d",
1408 __func__, btif_hf_cb[idx].num_active, num_active);
1409 send_indicator_update(BTA_AG_IND_CALL,
1410 ((num_active + num_held) > 0) ? 1 : 0);
1411 }
1412
1413 /* Held Changed? */
1414 if (num_held != btif_hf_cb[idx].num_held ||
1415 ((num_active == 0) && ((num_held + btif_hf_cb[idx].num_held) > 1))) {
1416 BTIF_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d", __func__,
1417 btif_hf_cb[idx].num_held, num_held);
1418 send_indicator_update(BTA_AG_IND_CALLHELD,
1419 ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
1420 }
1421
1422 /* Calls Swapped? */
1423 if ((call_setup_state == btif_hf_cb[idx].call_setup_state) &&
1424 (num_active && num_held) && (num_active == btif_hf_cb[idx].num_active) &&
1425 (num_held == btif_hf_cb[idx].num_held)) {
1426 BTIF_TRACE_DEBUG("%s: Calls swapped", __func__);
1427 send_indicator_update(BTA_AG_IND_CALLHELD, 1);
1428 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001429
1430update_call_states:
Myles Watson6bd442f2016-10-19 09:50:22 -07001431 for (i = 0; i < btif_max_hf_clients; i++) {
1432 if (btif_hf_cb[i].state == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
1433 btif_hf_cb[i].num_active = num_active;
1434 btif_hf_cb[i].num_held = num_held;
1435 btif_hf_cb[i].call_setup_state = call_setup_state;
Nitin Srivastava2cb90bc2014-03-14 16:19:58 -07001436 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001437 }
1438 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001439}
1440
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301441/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001442 *
1443 * Function btif_hf_is_call_idle
1444 *
1445 * Description returns true if no call is in progress
1446 *
1447 * Returns bt_status_t
1448 *
1449 ******************************************************************************/
1450bool btif_hf_is_call_idle(void) {
1451 if (bt_hf_callbacks == NULL) return true;
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301452
Myles Watson6bd442f2016-10-19 09:50:22 -07001453 for (int i = 0; i < btif_max_hf_clients; ++i) {
1454 if ((btif_hf_cb[i].call_setup_state != BTHF_CALL_STATE_IDLE) ||
1455 ((btif_hf_cb[i].num_held + btif_hf_cb[i].num_active) > 0))
1456 return false;
1457 }
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301458
Myles Watson6bd442f2016-10-19 09:50:22 -07001459 return true;
1460}
1461
1462/*******************************************************************************
1463 *
1464 * Function btif_hf_call_terminated_recently
1465 *
1466 * Description Checks if a call has been terminated
1467 *
1468 * Returns bt_status_t
1469 *
1470 ******************************************************************************/
1471bool btif_hf_call_terminated_recently() {
1472 struct timespec now;
1473
1474 clock_gettime(CLOCK_MONOTONIC, &now);
1475 if (now.tv_sec <
1476 btif_hf_cb[0].call_end_timestamp.tv_sec + BTIF_HF_CALL_END_TIMEOUT) {
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001477 return true;
Myles Watson6bd442f2016-10-19 09:50:22 -07001478 } else {
1479 btif_hf_cb[0].call_end_timestamp.tv_sec = 0;
1480 return false;
1481 }
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301482}
The Android Open Source Project5738f832012-12-12 16:00:35 -08001483
1484/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001485 *
1486 * Function cleanup
1487 *
1488 * Description Closes the HF interface
1489 *
1490 * Returns bt_status_t
1491 *
1492 ******************************************************************************/
1493static void cleanup(void) {
1494 BTIF_TRACE_EVENT("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001495
Jack Hed3668072017-09-14 17:13:19 -07001496 btif_queue_cleanup(UUID_SERVCLASS_AG_HANDSFREE);
Myles Watson6bd442f2016-10-19 09:50:22 -07001497 if (bt_hf_callbacks) {
Satish Kodishala0ff1dd72016-03-09 18:57:01 +05301498#if (defined(BTIF_HF_SERVICES) && (BTIF_HF_SERVICES & BTA_HFP_SERVICE_MASK))
Myles Watson6bd442f2016-10-19 09:50:22 -07001499 btif_disable_service(BTA_HFP_SERVICE_ID);
Satish Kodishala0ff1dd72016-03-09 18:57:01 +05301500#else
1501 btif_disable_service(BTA_HSP_SERVICE_ID);
1502#endif
Myles Watson6bd442f2016-10-19 09:50:22 -07001503 bt_hf_callbacks = NULL;
1504 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001505}
1506
1507/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001508 *
1509 * Function configure_wbs
1510 *
1511 * Description set to over-ride the current WBS configuration.
1512 * It will not send codec setting cmd to the controller now.
1513 * It just change the configure.
1514 *
1515 * Returns bt_status_t
1516 *
1517 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001518static bt_status_t configure_wbs(RawAddress* bd_addr,
Myles Watson6bd442f2016-10-19 09:50:22 -07001519 bthf_wbs_config_t config) {
1520 CHECK_BTHF_INIT();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001521
Myles Watson6bd442f2016-10-19 09:50:22 -07001522 int idx = btif_hf_idx_by_bdaddr(bd_addr);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001523
Myles Watson6bd442f2016-10-19 09:50:22 -07001524 if ((idx < 0) || (idx >= BTIF_HF_NUM_CB)) {
1525 BTIF_TRACE_ERROR("%s: Invalid index %d", __func__, idx);
1526 return BT_STATUS_FAIL;
1527 }
Matthew Xie66432dc2014-04-27 05:45:32 -07001528
Myles Watson6bd442f2016-10-19 09:50:22 -07001529 BTIF_TRACE_EVENT("%s config is %d", __func__, config);
1530 if (config == BTHF_WBS_YES)
1531 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
1532 else if (config == BTHF_WBS_NO)
1533 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_CVSD);
1534 else
1535 BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_NONE);
Matthew Xie66432dc2014-04-27 05:45:32 -07001536
Myles Watson6bd442f2016-10-19 09:50:22 -07001537 return BT_STATUS_SUCCESS;
Matthew Xie66432dc2014-04-27 05:45:32 -07001538}
1539
The Android Open Source Project5738f832012-12-12 16:00:35 -08001540static const bthf_interface_t bthfInterface = {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001541 sizeof(bthfInterface),
The Android Open Source Project5738f832012-12-12 16:00:35 -08001542 init,
1543 connect,
1544 disconnect,
1545 connect_audio,
1546 disconnect_audio,
1547 start_voice_recognition,
1548 stop_voice_recognition,
1549 volume_control,
1550 device_status_notification,
1551 cops_response,
1552 cind_response,
1553 formatted_at_response,
1554 at_response,
1555 clcc_response,
1556 phone_state_change,
1557 cleanup,
Matthew Xie66432dc2014-04-27 05:45:32 -07001558 configure_wbs,
Mudumba Ananth4de9bbc2016-02-29 02:21:43 -08001559 bind_response,
Zach Johnsonacdc11c2017-04-18 21:03:07 -07001560 set_sco_allowed,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001561};
1562
1563/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001564 *
1565 * Function btif_hf_execute_service
1566 *
1567 * Description Initializes/Shuts down the service
1568 *
1569 * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1570 *
1571 ******************************************************************************/
1572bt_status_t btif_hf_execute_service(bool b_enable) {
1573 const char* p_service_names[] = BTIF_HF_SERVICE_NAMES;
1574 int i;
1575 if (b_enable) {
1576 /* Enable and register with BTA-AG */
1577 BTA_AgEnable(BTA_AG_PARSE, bte_hf_evt);
1578 for (i = 0; i < btif_max_hf_clients; i++) {
Jack He7a9892c2017-02-02 17:42:40 -08001579 BTA_AgRegister(BTIF_HF_SERVICES, BTIF_HF_SECURITY, btif_hf_features,
Myles Watson6bd442f2016-10-19 09:50:22 -07001580 p_service_names, bthf_hf_id[i]);
1581 }
1582 } else {
1583 /* De-register AG */
1584 for (i = 0; i < btif_max_hf_clients; i++) {
1585 BTA_AgDeregister(btif_hf_cb[i].handle);
1586 }
1587 /* Disable AG */
1588 BTA_AgDisable();
1589 }
1590 return BT_STATUS_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001591}
1592
1593/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001594 *
1595 * Function btif_hf_get_interface
1596 *
1597 * Description Get the hf callback interface
1598 *
1599 * Returns bthf_interface_t
1600 *
1601 ******************************************************************************/
1602const bthf_interface_t* btif_hf_get_interface() {
1603 BTIF_TRACE_EVENT("%s", __func__);
1604 return &bthfInterface;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001605}