X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=btif%2Fsrc%2Fbtif_dm.c;h=2aceb6ea7efdbc1df2165871ce6ba6eeb21ddd19;hb=7bde09fe4aead831a63cad90d7c6f4931d5a0e00;hp=f84bb4a4f742bb6e44789b84da9a1c6fcbb87b27;hpb=3ee69e43c29f2268a3b0961f126b9cd7a8efcbd1;p=android-x86%2Fsystem-bt.git diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c index f84bb4a4f..2aceb6ea7 100644 --- a/btif/src/btif_dm.c +++ b/btif/src/btif_dm.c @@ -30,11 +30,13 @@ #include "btif_dm.h" #include +#include #include #include #include #include #include +#include #include #include @@ -61,9 +63,9 @@ #include "bta_gatt_api.h" #include "device/include/interop.h" #include "include/stack_config.h" -#include "osi/include/log.h" #include "osi/include/allocator.h" #include "osi/include/log.h" +#include "osi/include/metrics.h" #include "stack_config.h" #include "stack/btm/btm_int.h" @@ -149,11 +151,11 @@ typedef struct BD_NAME bd_name; } btif_dm_remote_name_t; +/* this structure holds optional OOB data for remote device */ typedef struct { - BT_OCTET16 sp_c; - BT_OCTET16 sp_r; - BD_ADDR oob_bdaddr; /* peer bdaddr*/ + BD_ADDR bdaddr; /* peer bdaddr */ + bt_out_of_band_data_t oob_data; } btif_dm_oob_cb_t; typedef struct @@ -177,11 +179,29 @@ typedef struct unsigned int manufact_id; }skip_sdp_entry_t; +typedef enum +{ + BTIF_DM_FUNC_CREATE_BOND, + BTIF_DM_FUNC_CANCEL_BOND, + BTIF_DM_FUNC_REMOVE_BOND, + BTIF_DM_FUNC_BOND_STATE_CHANGED, +} bt_bond_function_t; + +typedef struct +{ + bt_bdaddr_t bd_addr; + bt_bond_function_t function; + bt_bond_state_t state; + struct timespec timestamp; +} btif_bond_event_t; + #define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) #define MAX_SDP_BL_ENTRIES 3 #define UUID_HUMAN_INTERFACE_DEVICE "00001124-0000-1000-8000-00805f9b34fb" +#define MAX_BTIF_BOND_EVENT_ENTRIES 15 + static skip_sdp_entry_t sdp_blacklist[] = {{76}}; //Apple Mouse and Keyboard /* This flag will be true if HCI_Inquiry is in progress */ @@ -191,6 +211,18 @@ static BOOLEAN btif_dm_inquiry_in_progress = FALSE; ** Static variables ************************************************************************************/ static char btif_default_local_name[DEFAULT_LOCAL_NAME_MAX+1] = {'\0'}; +static uid_set_t* uid_set = NULL; + +/* A circular array to keep track of the most recent bond events */ +static btif_bond_event_t btif_dm_bond_events[MAX_BTIF_BOND_EVENT_ENTRIES + 1]; + +static pthread_mutex_t bond_event_lock; + +/* |btif_num_bond_events| keeps track of the total number of events and can be + greater than |MAX_BTIF_BOND_EVENT_ENTRIES| */ +static size_t btif_num_bond_events = 0; +static size_t btif_events_start_index = 0; +static size_t btif_events_end_index = 0; /****************************************************************************** ** Static functions @@ -208,13 +240,20 @@ static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif); static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl); static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req); static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) ; +static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type); #endif static void bte_scan_filt_param_cfg_evt(UINT8 action_type, tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, - tBTA_DM_BLE_REF_VALUE ref_value, tBTA_STATUS status); + tBTA_DM_BLE_REF_VALUE ref_value, + tBTA_STATUS status); static char* btif_get_default_local_name(); + +static void btif_stats_add_bond_event(const bt_bdaddr_t *bd_addr, + bt_bond_function_t function, + bt_bond_state_t state); + /****************************************************************************** ** Externs ******************************************************************************/ @@ -232,6 +271,12 @@ extern void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UIN ** Functions ******************************************************************************/ +static bool is_empty_128bit(uint8_t *data) +{ + static const uint8_t zero[16] = { 0 }; + return !memcmp(zero, data, sizeof(zero)); +} + static void btif_dm_data_copy(uint16_t event, char *dst, char *src) { tBTA_DM_SEC *dst_dm_sec = (tBTA_DM_SEC*)dst; @@ -247,7 +292,6 @@ static void btif_dm_data_copy(uint16_t event, char *dst, char *src) { dst_dm_sec->ble_key.p_key_value = osi_malloc(sizeof(tBTM_LE_KEY_VALUE)); assert(src_dm_sec->ble_key.p_key_value); - assert(dst_dm_sec->ble_key.p_key_value); memcpy(dst_dm_sec->ble_key.p_key_value, src_dm_sec->ble_key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); } } @@ -255,7 +299,19 @@ static void btif_dm_data_copy(uint16_t event, char *dst, char *src) static void btif_dm_data_free(uint16_t event, tBTA_DM_SEC *dm_sec) { if (event == BTA_DM_BLE_KEY_EVT) - osi_free(dm_sec->ble_key.p_key_value); + osi_free_and_reset((void **)&dm_sec->ble_key.p_key_value); +} + +void btif_dm_init(uid_set_t* set) +{ + uid_set = set; + pthread_mutex_init(&bond_event_lock, NULL); +} + +void btif_dm_cleanup(void) +{ + uid_set = NULL; + pthread_mutex_destroy(&bond_event_lock); } bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id, @@ -485,6 +541,9 @@ BOOLEAN check_sdp_bl(const bt_bdaddr_t *remote_bdaddr) static void bond_state_changed(bt_status_t status, bt_bdaddr_t *bd_addr, bt_bond_state_t state) { + + btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_BOND_STATE_CHANGED, state); + // Send bonding state only once - based on outgoing/incoming we may receive duplicates if ((pairing_cb.state == state) && (state == BT_BOND_STATE_BONDING)) { @@ -823,12 +882,9 @@ static void search_services_copy_cb(UINT16 event, char *p_dest, char *p_src) (UINT8*)(p_dest + sizeof(tBTA_DM_SEARCH)); memcpy(p_dest_data->disc_res.p_uuid_list, p_src_data->disc_res.p_uuid_list, p_src_data->disc_res.num_uuids*MAX_UUID_SIZE); - osi_freebuf(p_src_data->disc_res.p_uuid_list); - } - if (p_src_data->disc_res.p_raw_data != NULL) - { - osi_freebuf(p_src_data->disc_res.p_raw_data); + osi_free_and_reset((void **)&p_src_data->disc_res.p_uuid_list); } + osi_free_and_reset((void **)&p_src_data->disc_res.p_raw_data); } } break; } @@ -1090,6 +1146,20 @@ static void btif_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) } } + // We could have received a new link key without going through the pairing flow. + // If so, we don't want to perform SDP or any other operations on the authenticated + // device. + if (bdcmp(p_auth_cmpl->bd_addr, pairing_cb.bd_addr) != 0) { + char address[32]; + bt_bdaddr_t bt_bdaddr; + + memcpy(bt_bdaddr.address, p_auth_cmpl->bd_addr, + sizeof(bt_bdaddr.address)); + bdaddr_to_string(&bt_bdaddr, address, sizeof(address)); + LOG_INFO(LOG_TAG, "%s skipping SDP since we did not initiate pairing to %s.", __func__, address); + return; + } + // Skip SDP for certain HID Devices if (p_auth_cmpl->success) { @@ -1866,6 +1936,7 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) break; case BTA_DM_BLE_OOB_REQ_EVT: BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. "); + btif_dm_ble_oob_req_evt(&p_data->rmt_oob); break; case BTA_DM_BLE_LOCAL_IR_EVT: BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. "); @@ -1946,7 +2017,10 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) energy_info.tx_time = p_ener_data->tx_time; energy_info.idle_time = p_ener_data->idle_time; energy_info.energy_used = p_ener_data->energy_used; - HAL_CBACK(bt_hal_cbacks, energy_info_cb, &energy_info); + + bt_uid_traffic_t* data = uid_set_read_and_clear(uid_set); + HAL_CBACK(bt_hal_cbacks, energy_info_cb, &energy_info, data); + osi_free(data); break; } #endif @@ -2306,6 +2380,8 @@ bt_status_t btif_dm_create_bond(const bt_bdaddr_t *bd_addr, int transport) if (pairing_cb.state != BT_BOND_STATE_NONE) return BT_STATUS_BUSY; + btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_CREATE_BOND, pairing_cb.state); + btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_CREATE_BOND, (char *)&create_bond_cb, sizeof(btif_dm_create_bond_cb_t), NULL); @@ -2314,6 +2390,25 @@ bt_status_t btif_dm_create_bond(const bt_bdaddr_t *bd_addr, int transport) /******************************************************************************* ** +** Function btif_dm_create_bond_out_of_band +** +** Description Initiate bonding with the specified device using out of band data +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btif_dm_create_bond_out_of_band(const bt_bdaddr_t *bd_addr, int transport, const bt_out_of_band_data_t *oob_data) +{ + bdcpy(oob_cb.bdaddr, bd_addr->address); + memcpy(&oob_cb.oob_data, oob_data, sizeof(bt_out_of_band_data_t)); + + bdstr_t bdstr; + BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport); + return btif_dm_create_bond(bd_addr, transport); +} + +/******************************************************************************* +** ** Function btif_dm_cancel_bond ** ** Description Initiate bonding with the specified device @@ -2328,6 +2423,8 @@ bt_status_t btif_dm_cancel_bond(const bt_bdaddr_t *bd_addr) BTIF_TRACE_EVENT("%s: bd_addr=%s", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr))); + btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_CANCEL_BOND, pairing_cb.state); + /* TODO: ** 1. Restore scan modes ** 2. special handling for HID devices @@ -2416,6 +2513,9 @@ bt_status_t btif_dm_remove_bond(const bt_bdaddr_t *bd_addr) bdstr_t bdstr; BTIF_TRACE_EVENT("%s: bd_addr=%s", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr))); + + btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_REMOVE_BOND, pairing_cb.state); + btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_REMOVE_BOND, (char *)bd_addr, sizeof(bt_bdaddr_t), NULL); @@ -2716,21 +2816,49 @@ void btif_dm_proc_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap, } } -#if (BTM_OOB_INCLUDED == TRUE) -void btif_dm_set_oob_for_io_req(tBTA_OOB_DATA *p_oob_data) +void btif_dm_set_oob_for_io_req(tBTA_OOB_DATA *p_has_oob_data) +{ + if (is_empty_128bit(oob_cb.oob_data.c192)) + { + *p_has_oob_data = FALSE; + } + else + { + *p_has_oob_data = TRUE; + } + BTIF_TRACE_DEBUG("%s: *p_has_oob_data=%d", __func__, *p_has_oob_data); +} + +void btif_dm_set_oob_for_le_io_req(BD_ADDR bd_addr, tBTA_OOB_DATA *p_has_oob_data, + tBTA_LE_AUTH_REQ *p_auth_req) { - if (oob_cb.sp_c[0] == 0 && oob_cb.sp_c[1] == 0 && - oob_cb.sp_c[2] == 0 && oob_cb.sp_c[3] == 0 ) + + /* We currently support only Security Manager TK as OOB data for LE transport. + If it's not present mark no OOB data. + */ + if (!is_empty_128bit(oob_cb.oob_data.sm_tk)) { - *p_oob_data = FALSE; + /* make sure OOB data is for this particular device */ + if (memcmp(bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) == 0) { + // When using OOB with TK, SC Secure Connections bit must be disabled. + tBTA_LE_AUTH_REQ mask = ~BTM_LE_AUTH_REQ_SC_ONLY; + *p_auth_req = ((*p_auth_req) & mask); + + *p_has_oob_data = TRUE; + } + else + { + *p_has_oob_data = FALSE; + BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address", + __func__); + } } else { - *p_oob_data = TRUE; + *p_has_oob_data = FALSE; } - BTIF_TRACE_DEBUG("btif_dm_set_oob_for_io_req *p_oob_data=%d", *p_oob_data); + BTIF_TRACE_DEBUG("%s *p_has_oob_data=%d", __func__, *p_has_oob_data); } -#endif /* BTM_OOB_INCLUDED */ #ifdef BTIF_DM_OOB_TEST void btif_dm_load_local_oob(void) @@ -2743,19 +2871,14 @@ void btif_dm_load_local_oob(void) #if !defined(OS_GENERIC) char prop_oob[PROPERTY_VALUE_MAX]; property_get("service.brcm.bt.oob", prop_oob, "3"); - BTIF_TRACE_DEBUG("btif_dm_load_local_oob prop_oob = %s",prop_oob); + BTIF_TRACE_DEBUG("%s: prop_oob = %s", __func__, prop_oob); if (prop_oob[0] != '3') { -#if (BTM_OOB_INCLUDED == TRUE) - if (oob_cb.sp_c[0] == 0 && oob_cb.sp_c[1] == 0 && - oob_cb.sp_c[2] == 0 && oob_cb.sp_c[3] == 0 ) + if (is_empty_128bit(oob_cb.oob_data.c192)) { - BTIF_TRACE_DEBUG("btif_dm_load_local_oob: read OOB, call BTA_DmLocalOob()"); + BTIF_TRACE_DEBUG("%s: read OOB, call BTA_DmLocalOob()", __func__); BTA_DmLocalOob(); } -#else /* (BTM_OOB_INCLUDED != TRUE) */ - BTIF_TRACE_ERROR("BTM_OOB_INCLUDED is FALSE!!(btif_dm_load_local_oob)"); -#endif /* (BTM_OOB_INCLUDED == TRUE) */ } #endif /* !defined(OS_GENERIC) */ } @@ -2773,16 +2896,14 @@ void btif_dm_proc_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r) char *path_b = "/data/misc/bluedroid/LOCAL/b.key"; char *path = NULL; char prop_oob[PROPERTY_VALUE_MAX]; - BTIF_TRACE_DEBUG("btif_dm_proc_loc_oob: valid=%d", valid); - if (oob_cb.sp_c[0] == 0 && oob_cb.sp_c[1] == 0 && - oob_cb.sp_c[2] == 0 && oob_cb.sp_c[3] == 0 && - valid) + BTIF_TRACE_DEBUG("%s: valid=%d", __func__, valid); + if (is_empty_128bit(oob_cb.oob_data.c192) && valid) { BTIF_TRACE_DEBUG("save local OOB data in memory"); - memcpy(oob_cb.sp_c, c, BT_OCTET16_LEN); - memcpy(oob_cb.sp_r, r, BT_OCTET16_LEN); + memcpy(oob_cb.oob_data.c192, c, BT_OCTET16_LEN); + memcpy(oob_cb.oob_data.r192, r, BT_OCTET16_LEN); property_get("service.brcm.bt.oob", prop_oob, "3"); - BTIF_TRACE_DEBUG("btif_dm_proc_loc_oob prop_oob = %s",prop_oob); + BTIF_TRACE_DEBUG("%s: prop_oob = %s", __func__, prop_oob); if (prop_oob[0] == '1') path = path_a; else if (prop_oob[0] == '2') @@ -2792,11 +2913,11 @@ void btif_dm_proc_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r) fp = fopen(path, "wb+"); if (fp == NULL) { - BTIF_TRACE_DEBUG("btif_dm_proc_loc_oob: failed to save local OOB data to %s", path); + BTIF_TRACE_DEBUG("%s: failed to save local OOB data to %s", __func__, path); } else { - BTIF_TRACE_DEBUG("btif_dm_proc_loc_oob: save local OOB data into file %s",path); + BTIF_TRACE_DEBUG("%s: save local OOB data into file %s", __func__, path); fwrite (c , 1 , BT_OCTET16_LEN , fp ); fwrite (r , 1 , BT_OCTET16_LEN , fp ); fclose(fp); @@ -2822,9 +2943,9 @@ BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr, BT_OCTET16 p_c, BT_OCTET16 p_r) char prop_oob[PROPERTY_VALUE_MAX]; BOOLEAN result = FALSE; bt_bdaddr_t bt_bd_addr; - bdcpy(oob_cb.oob_bdaddr, bd_addr); + bdcpy(oob_cb.bdaddr, bd_addr); property_get("service.brcm.bt.oob", prop_oob, "3"); - BTIF_TRACE_DEBUG("btif_dm_proc_rmt_oob prop_oob = %s",prop_oob); + BTIF_TRACE_DEBUG("%s: prop_oob = %s", __func__, prop_oob); if (prop_oob[0] == '1') path = path_b; else if (prop_oob[0] == '2') @@ -2834,35 +2955,35 @@ BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr, BT_OCTET16 p_c, BT_OCTET16 p_r) fp = fopen(path, "rb"); if (fp == NULL) { - BTIF_TRACE_DEBUG("btapp_dm_rmt_oob_reply: failed to read OOB keys from %s",path); + BTIF_TRACE_DEBUG("%s: failed to read OOB keys from %s", __func__, path); return FALSE; } else { - BTIF_TRACE_DEBUG("btif_dm_proc_rmt_oob: read OOB data from %s",path); + BTIF_TRACE_DEBUG("%s: read OOB data from %s", __func__, path); fread (p_c , 1 , BT_OCTET16_LEN , fp ); fread (p_r , 1 , BT_OCTET16_LEN , fp ); fclose(fp); } - BTIF_TRACE_DEBUG("----btif_dm_proc_rmt_oob: TRUE"); + BTIF_TRACE_DEBUG("----%s: TRUE", __func__); sprintf(t, "%02x:%02x:%02x:%02x:%02x:%02x", - oob_cb.oob_bdaddr[0], oob_cb.oob_bdaddr[1], oob_cb.oob_bdaddr[2], - oob_cb.oob_bdaddr[3], oob_cb.oob_bdaddr[4], oob_cb.oob_bdaddr[5]); - BTIF_TRACE_DEBUG("----btif_dm_proc_rmt_oob: peer_bdaddr = %s", t); + oob_cb.bdaddr[0], oob_cb.bdaddr[1], oob_cb.bdaddr[2], + oob_cb.bdaddr[3], oob_cb.bdaddr[4], oob_cb.bdaddr[5]); + BTIF_TRACE_DEBUG("----%s: peer_bdaddr = %s", __func__, t); sprintf(t, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", p_c[0], p_c[1], p_c[2], p_c[3], p_c[4], p_c[5], p_c[6], p_c[7], p_c[8], p_c[9], p_c[10], p_c[11], p_c[12], p_c[13], p_c[14], p_c[15]); - BTIF_TRACE_DEBUG("----btif_dm_proc_rmt_oob: c = %s",t); + BTIF_TRACE_DEBUG("----%s: c = %s", __func__, t); sprintf(t, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", p_r[0], p_r[1], p_r[2], p_r[3], p_r[4], p_r[5], p_r[6], p_r[7], p_r[8], p_r[9], p_r[10], p_r[11], p_r[12], p_r[13], p_r[14], p_r[15]); - BTIF_TRACE_DEBUG("----btif_dm_proc_rmt_oob: r = %s",t); + BTIF_TRACE_DEBUG("----%s: r = %s", __func__, t); bdcpy(bt_bd_addr.address, bd_addr); btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_BOND_STATE_BONDING, (char *)&bt_bd_addr, sizeof(bt_bdaddr_t), NULL); result = TRUE; } - BTIF_TRACE_DEBUG("btif_dm_proc_rmt_oob result=%d",result); + BTIF_TRACE_DEBUG("%s: result=%d", __func__, result); return result; #else /* defined(OS_GENERIC) */ return FALSE; @@ -2916,6 +3037,10 @@ static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) bt_bond_state_t state = BT_BOND_STATE_NONE; bdcpy(bd_addr.address, p_auth_cmpl->bd_addr); + + /* Clear OOB data */ + memset(&oob_cb, 0, sizeof(oob_cb)); + if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) ) { /* store keys */ @@ -3184,6 +3309,39 @@ static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) p_notif_req->passkey); } +static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type) +{ + BTIF_TRACE_DEBUG("%s", __FUNCTION__); + + bt_bdaddr_t bd_addr; + bdcpy(bd_addr.address, req_oob_type->bd_addr); + + /* We currently support only Security Manager TK as OOB data. We already + * checked if it's present in btif_dm_set_oob_for_le_io_req, but check here + * again. If it's not present do nothing, pairing will timeout. + */ + if (is_empty_128bit(oob_cb.oob_data.sm_tk)) { + return; + } + + /* make sure OOB data is for this particular device */ + if (memcmp(req_oob_type->bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) != 0) { + BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address", __func__); + return; + } + + /* Remote name update */ + btif_update_remote_properties(req_oob_type->bd_addr , req_oob_type->bd_name, + NULL, BT_DEVICE_TYPE_BLE); + + bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING); + pairing_cb.is_ssp = FALSE; + pairing_cb.is_le_only = TRUE; + pairing_cb.is_le_nc = FALSE; + + BTM_BleOobDataReply(req_oob_type->bd_addr, 0, 16, oob_cb.oob_data.sm_tk); +} + void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE dev_type) { @@ -3292,3 +3450,101 @@ static char* btif_get_default_local_name() { #endif /* !defined(OS_GENERIC) */ return btif_default_local_name; } + +static void btif_stats_add_bond_event(const bt_bdaddr_t *bd_addr, + bt_bond_function_t function, + bt_bond_state_t state) { + pthread_mutex_lock(&bond_event_lock); + + btif_bond_event_t* event = &btif_dm_bond_events[btif_events_end_index]; + memcpy(&event->bd_addr, bd_addr, sizeof(bt_bdaddr_t)); + event->function = function; + event->state = state; + clock_gettime(CLOCK_MONOTONIC, &event->timestamp); + + btif_num_bond_events++; + btif_events_end_index = (btif_events_end_index + 1) % (MAX_BTIF_BOND_EVENT_ENTRIES + 1); + if (btif_events_end_index == btif_events_start_index) { + btif_events_start_index = (btif_events_start_index + 1) % (MAX_BTIF_BOND_EVENT_ENTRIES + 1); + } + + int type; + btif_get_device_type(event->bd_addr.address, &type); + device_type_t device_type; + switch (type) { + case BT_DEVICE_TYPE_BREDR: + device_type = DEVICE_TYPE_BREDR; + break; + case BT_DEVICE_TYPE_BLE: + device_type = DEVICE_TYPE_LE; + break; + case BT_DEVICE_TYPE_DUMO: + device_type = DEVICE_TYPE_DUMO; + break; + default: + device_type = DEVICE_TYPE_UNKNOWN; + break; + } + // TODO (apanicke): Add disconnect reason and + // device class to the pair event. + uint64_t ts = event->timestamp.tv_sec * 1000 + + event->timestamp.tv_nsec / 1000000; + metrics_pair_event(0, ts, 0, device_type); + + pthread_mutex_unlock(&bond_event_lock); +} + +void btif_debug_bond_event_dump(int fd) { + pthread_mutex_lock(&bond_event_lock); + dprintf(fd, "\nBond Events: \n"); + dprintf(fd, " Total Number of events: %zu\n", btif_num_bond_events); + if (btif_num_bond_events > 0) + dprintf(fd, " Time BD_ADDR Function State\n"); + + for (size_t i = btif_events_start_index; i != btif_events_end_index; + i = (i + 1) % (MAX_BTIF_BOND_EVENT_ENTRIES + 1)) { + btif_bond_event_t* event = &btif_dm_bond_events[i]; + + char eventtime[15]; + struct tm *tstamp = localtime(&event->timestamp.tv_sec); + strftime(eventtime, sizeof(eventtime), "%H:%M:%S.%%03u", tstamp); + snprintf(eventtime, sizeof(eventtime), eventtime, (event->timestamp.tv_nsec) / 1000000); + + char bdaddr[18]; + bdaddr_to_string(&event->bd_addr, bdaddr, sizeof(bdaddr)); + + char* func_name; + switch (event->function) { + case BTIF_DM_FUNC_CREATE_BOND: + func_name = "btif_dm_create_bond"; + break; + case BTIF_DM_FUNC_REMOVE_BOND: + func_name = "btif_dm_remove_bond"; + break; + case BTIF_DM_FUNC_BOND_STATE_CHANGED: + func_name = "bond_state_changed "; + break; + default: + func_name = "Invalid value "; + break; + } + + char* bond_state; + switch (event->state) { + case BT_BOND_STATE_NONE: + bond_state = "BOND_STATE_NONE"; + break; + case BT_BOND_STATE_BONDING: + bond_state = "BOND_STATE_BONDING"; + break; + case BT_BOND_STATE_BONDED: + bond_state = "BOND_STATE_BONDED"; + break; + default: + bond_state = "Invalid bond state"; + break; + } + dprintf(fd, " %s %s %s %s\n", eventtime, bdaddr, func_name, bond_state); + } + pthread_mutex_unlock(&bond_event_lock); +}