system/bt
Revision | e7bec445b8d20e153fcf7cb46c0da6020d1c96fd (tree) |
---|---|
Zeit | 2017-04-14 17:47:18 |
Autor | Linux Build Service Account <lnxbuild@loca...> |
Commiter | Linux Build Service Account |
Promotion of bt.lnx.2.1.c1-00046.
CRs Change ID Subject
Change-Id: Iad5b862b89b66ceb0345caf8f5a3c0bf44b0c21c
@@ -177,7 +177,7 @@ enum | ||
177 | 177 | BTA_AG_RES_FMT_STR /* string argument */ |
178 | 178 | }; |
179 | 179 | |
180 | -/* enumeration of AT result codes, matches constant table */ | |
180 | +/* Local AT command result codes not defined in bta_ag_api.h */ | |
181 | 181 | enum |
182 | 182 | { |
183 | 183 | BTA_AG_RES_OK, |
@@ -207,7 +207,7 @@ enum | ||
207 | 207 | #if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE) |
208 | 208 | #define COLON_IDX_4_VGSVGM 4 |
209 | 209 | #endif |
210 | -/* AT result code constant table (Indexed by result code) */ | |
210 | +/* AT result code constant table */ | |
211 | 211 | const tBTA_AG_RESULT bta_ag_result_tbl[] = |
212 | 212 | { |
213 | 213 | {"OK", BTA_AG_RES_FMT_NONE}, |
@@ -234,6 +234,7 @@ const tBTA_AG_RESULT bta_ag_result_tbl[] = | ||
234 | 234 | {"+BIND: ", BTA_AG_RES_FMT_STR}, |
235 | 235 | }; |
236 | 236 | |
237 | + | |
237 | 238 | const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX] = |
238 | 239 | { |
239 | 240 | bta_ag_hsp_cmd, |
@@ -350,10 +351,10 @@ const UINT8 bta_ag_callsetup_ind_tbl[] = | ||
350 | 351 | static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg, |
351 | 352 | INT16 int_arg) |
352 | 353 | { |
353 | - char buf[BTA_AG_AT_MAX_LEN + 16]; | |
354 | - char *p = buf; | |
355 | - UINT16 len; | |
356 | 354 | |
355 | + char buf[BTA_AG_AT_MAX_LEN + 16]; | |
356 | + char *p = buf; | |
357 | + UINT16 len; | |
357 | 358 | #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE) |
358 | 359 | memset(buf, NULL, sizeof(buf)); |
359 | 360 | #endif |
@@ -364,7 +365,7 @@ static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg, | ||
364 | 365 | /* copy result code string */ |
365 | 366 | strlcpy(p, bta_ag_result_tbl[code].p_res, sizeof(buf) - 2); |
366 | 367 | #if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE) |
367 | - if(p_scb->conn_service == BTA_AG_HSP) | |
368 | + if (p_scb->conn_service == BTA_AG_HSP) | |
368 | 369 | { |
369 | 370 | /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */ |
370 | 371 | switch(code) |
@@ -972,7 +973,6 @@ void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, | ||
972 | 973 | char *p_arg, INT16 int_arg) |
973 | 974 | { |
974 | 975 | tBTA_AG_VAL val; |
975 | - | |
976 | 976 | APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type, |
977 | 977 | int_arg, p_arg); |
978 | 978 |
@@ -987,7 +987,6 @@ void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, | ||
987 | 987 | /* call callback with event */ |
988 | 988 | (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val); |
989 | 989 | } |
990 | - | |
991 | 990 | /******************************************************************************* |
992 | 991 | ** |
993 | 992 | ** Function bta_ag_at_hfp_cback |
@@ -1368,6 +1367,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, | ||
1368 | 1367 | |
1369 | 1368 | case BTA_AG_HF_CMD_CNUM: |
1370 | 1369 | break; |
1370 | + | |
1371 | 1371 | case BTA_AG_HF_CMD_CLCC: |
1372 | 1372 | if(!(p_scb->features & BTA_AG_FEAT_ECS)) |
1373 | 1373 | { |
@@ -1562,7 +1562,6 @@ void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg) | ||
1562 | 1562 | void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result) |
1563 | 1563 | { |
1564 | 1564 | UINT8 code = bta_ag_trans_result[p_result->result]; |
1565 | - | |
1566 | 1565 | APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result); |
1567 | 1566 | |
1568 | 1567 | switch(p_result->result) |
@@ -28,6 +28,7 @@ | ||
28 | 28 | #include "bta_api.h" |
29 | 29 | #include "bta_ag_api.h" |
30 | 30 | #include "bta_ag_at.h" |
31 | +#include "osi/include/log.h" | |
31 | 32 | |
32 | 33 | /* Send RING & CLIP in one AT cmd */ |
33 | 34 | #ifndef BTA_AG_MULTI_RESULT_INCLUDED |
@@ -2952,6 +2952,8 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data) | ||
2952 | 2952 | /*case BTM_SP_KEY_REQ_EVT: */ |
2953 | 2953 | case BTM_SP_KEY_NOTIF_EVT: |
2954 | 2954 | #endif |
2955 | + bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey; | |
2956 | + | |
2955 | 2957 | if(BTM_SP_CFM_REQ_EVT == event) |
2956 | 2958 | { |
2957 | 2959 | /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT, |
@@ -2982,7 +2984,6 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data) | ||
2982 | 2984 | } |
2983 | 2985 | } |
2984 | 2986 | |
2985 | - bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey; | |
2986 | 2987 | if (BTM_SP_KEY_NOTIF_EVT == event) |
2987 | 2988 | { |
2988 | 2989 | /* If the device name is not known, save bdaddr and devclass |
@@ -4482,6 +4483,11 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D | ||
4482 | 4483 | bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event); |
4483 | 4484 | break; |
4484 | 4485 | |
4486 | + case BTM_LE_SC_OOB_REQ_EVT: | |
4487 | + bdcpy(sec_event.ble_req.bd_addr, bda); | |
4488 | + bta_dm_cb.p_sec_cback(BTA_DM_BLE_SC_OOB_REQ_EVT, &sec_event); | |
4489 | + break; | |
4490 | + | |
4485 | 4491 | case BTM_LE_KEY_EVT: |
4486 | 4492 | bdcpy(sec_event.ble_key.bd_addr, bda); |
4487 | 4493 | sec_event.ble_key.key_type = p_data->key.key_type; |
@@ -326,7 +326,8 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, | ||
326 | 326 | descriptor->handle = handle; |
327 | 327 | memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID)); |
328 | 328 | |
329 | - if (service->characteristics == NULL) { | |
329 | + if (service->characteristics == NULL || | |
330 | + list_is_empty(service->characteristics)) { | |
330 | 331 | APPL_TRACE_ERROR("%s: Illegal action to add descriptor before adding a characteristic!", |
331 | 332 | __func__); |
332 | 333 | osi_free(descriptor); |
@@ -302,6 +302,12 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb) | ||
302 | 302 | p_srcb->connected = FALSE; |
303 | 303 | p_srcb->state = BTA_GATTC_SERV_IDLE; |
304 | 304 | p_srcb->mtu = 0; |
305 | + | |
306 | + /* clean up cache */ | |
307 | + if (p_srcb->p_srvc_cache) { | |
308 | + list_free(p_srcb->p_srvc_cache); | |
309 | + p_srcb->p_srvc_cache = NULL; | |
310 | + } | |
305 | 311 | } |
306 | 312 | |
307 | 313 | osi_free_and_reset((void **)&p_clcb->p_q_cmd); |
@@ -2182,12 +2182,19 @@ void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data) | ||
2182 | 2182 | |
2183 | 2183 | if (p_dev_cb == NULL) |
2184 | 2184 | { |
2185 | - APPL_TRACE_ERROR("notification received from Unknown device"); | |
2185 | + APPL_TRACE_ERROR("%s: notification received from Unknown device, conn_id: 0x%04x", | |
2186 | + __func__, p_data->conn_id); | |
2186 | 2187 | return; |
2187 | 2188 | } |
2188 | 2189 | |
2189 | 2190 | const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id, |
2190 | 2191 | p_data->handle); |
2192 | + if (p_char == NULL) | |
2193 | + { | |
2194 | + APPL_TRACE_ERROR("%s: notification received for Unknown Characteristic, conn_id: 0x%04x, handle: 0x%04x", | |
2195 | + __func__, p_dev_cb->conn_id, p_data->handle); | |
2196 | + return; | |
2197 | + } | |
2191 | 2198 | |
2192 | 2199 | if (p_char == NULL) { |
2193 | 2200 | APPL_TRACE_ERROR("%s: notification received for Unknown Characteristic,handle: 0x%04x", |
@@ -2208,7 +2215,8 @@ void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data) | ||
2208 | 2215 | p_char->handle); |
2209 | 2216 | if (p_rpt == NULL) |
2210 | 2217 | { |
2211 | - APPL_TRACE_ERROR("notification received for Unknown Report"); | |
2218 | + APPL_TRACE_ERROR("%s: notification received for Unknown Report, uuid: 0x%04x, handle: 0x%04x", | |
2219 | + __func__, p_char->uuid.uu.uuid16, p_char->handle); | |
2212 | 2220 | return; |
2213 | 2221 | } |
2214 | 2222 |
@@ -593,7 +593,8 @@ typedef UINT8 tBTA_SIG_STRENGTH_MASK; | ||
593 | 593 | #define BTA_DM_HW_ERROR_EVT 26 /* BT Chip H/W error */ |
594 | 594 | #define BTA_DM_LE_FEATURES_READ 27 /* Cotroller specific LE features are read */ |
595 | 595 | #define BTA_DM_ENER_INFO_READ 28 /* Energy info read */ |
596 | -typedef UINT8 tBTA_DM_SEC_EVT; | |
596 | +#define BTA_DM_BLE_SC_OOB_REQ_EVT 29 /* SMP SC OOB request event */ | |
597 | +typedef uint8_t tBTA_DM_SEC_EVT; | |
597 | 598 | |
598 | 599 | /* Structure associated with BTA_DM_ENABLE_EVT */ |
599 | 600 | typedef struct |
@@ -36,6 +36,7 @@ btifCommonSrc += \ | ||
36 | 36 | src/btif_debug.c \ |
37 | 37 | src/btif_debug_btsnoop.c \ |
38 | 38 | src/btif_debug_conn.c \ |
39 | + src/btif_debug_l2c.c \ | |
39 | 40 | src/btif_dm.c \ |
40 | 41 | src/btif_gatt.c \ |
41 | 42 | src/btif_gatt_client.c \ |
@@ -24,6 +24,9 @@ | ||
24 | 24 | #include "bta_dm_ci.h" |
25 | 25 | #include "bt_utils.h" |
26 | 26 | #include "btif_dm.h" |
27 | +#if (defined WEAR_LE_IO_CAP_OVERRIDE && WEAR_LE_IO_CAP_OVERRIDE == TRUE) | |
28 | +#include "btif_storage.h" | |
29 | +#endif | |
27 | 30 | #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) |
28 | 31 | #include "bte_appl.h" |
29 | 32 |
@@ -408,7 +411,24 @@ void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap, | ||
408 | 411 | tBTA_LE_KEY_TYPE *p_resp_key ) |
409 | 412 | { |
410 | 413 | UNUSED(bd_addr); |
411 | - /* Retrieve the properties from file system if possible */ | |
414 | + | |
415 | + | |
416 | +#if (defined WEAR_LE_IO_CAP_OVERRIDE && WEAR_LE_IO_CAP_OVERRIDE == TRUE) | |
417 | + /* | |
418 | + * Note: This is a Wear-specific feature for iOS pairing. | |
419 | + * | |
420 | + * Set WearLeIoCap config to force local IO capability to be BTM_IO_CAP_NONE | |
421 | + * (No input, no output) for the first bond creation, that indirectly | |
422 | + * triggers Just Works pairing. | |
423 | + */ | |
424 | + if (btif_storage_get_num_bonded_devices() == 0) | |
425 | + bte_appl_cfg.ble_io_cap = BTM_IO_CAP_NONE; | |
426 | +#endif | |
427 | + | |
428 | + /* For certification testing purpose, LE IO capability can also be specified with | |
429 | + * "PTS_SmpOptions" in the BT stack configuration file (i.e. bt_stack.conf). | |
430 | + * Note that if "PTS_SmpOptions" is set, it could override IO capability set above. | |
431 | + */ | |
412 | 432 | tBTE_APPL_CFG nv_config; |
413 | 433 | if(btif_dm_get_smp_config(&nv_config)) |
414 | 434 | bte_appl_cfg = nv_config; |
@@ -0,0 +1,54 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2016 Google Inc. | |
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 | + | |
19 | +#pragma once | |
20 | + | |
21 | +#include <stdint.h> | |
22 | + | |
23 | +#include <hardware/bluetooth.h> | |
24 | + | |
25 | +// Captures a BLE connection parameter update request (Section 4.20 of | |
26 | +// Bluetooth Core V4.2 specification): | |
27 | +// | |
28 | +// |min_interval| and |max_interval| define the minimum and maximum values for | |
29 | +// the connection event interval (in units of 1.25ms and should be in the | |
30 | +// [6, 3200] range). | |
31 | +// |slave_latency_param| is the slave latency parameter for the connection in | |
32 | +// number of connection events (unitless and should be less than 500). | |
33 | +// |timeout_multiplier| is the connection timeout parameter (in units of 10ms | |
34 | +// and should be in the [10, 3200] range). | |
35 | +void btif_debug_ble_connection_update_request(bt_bdaddr_t bda, | |
36 | + uint16_t min_interval, uint16_t max_interval, uint16_t slave_latency_param, | |
37 | + uint16_t timeout_multiplier); | |
38 | + | |
39 | +// Captures a BLE connection parameter update response ((Section 4.21 of | |
40 | +// Bluetooth Core V4.2 specification): | |
41 | +// | |
42 | +// |interval| defines the minimum and maximum values for the | |
43 | +// connection event interval (in units of 1.25ms and should be in the | |
44 | +// [6, 3200] range). | |
45 | +// |slave_latency_param| is the slave latency parameter for the connection in | |
46 | +// number of connection events (unitless and should be less than 500). | |
47 | +// |timeout_multiplier| is the connection timeout parameter (in units of 10ms | |
48 | +// and should be in the [10, 3200] range). | |
49 | +void btif_debug_ble_connection_update_response(bt_bdaddr_t bda, uint8_t status, | |
50 | + uint16_t interval, uint16_t slave_latency_param, | |
51 | + uint16_t timeout_multiplier); | |
52 | + | |
53 | +// Dumps captured L2C information. | |
54 | +void btif_debug_l2c_dump(int fd); |
@@ -286,6 +286,16 @@ bt_status_t btif_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr); | ||
286 | 286 | *******************************************************************************/ |
287 | 287 | BOOLEAN btif_storage_is_restricted_device(const bt_bdaddr_t *remote_bd_addr); |
288 | 288 | |
289 | +/******************************************************************************* | |
290 | +** | |
291 | +** Function btif_storage_get_num_bonded_devices | |
292 | +** | |
293 | +** Description BTIF storage API - Gets the number of bonded devices | |
294 | +** | |
295 | +** Returns the number of bonded devices | |
296 | +** | |
297 | +*******************************************************************************/ | |
298 | +int btif_storage_get_num_bonded_devices(void); | |
289 | 299 | #if (BLE_INCLUDED == TRUE) |
290 | 300 | bt_status_t btif_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr, |
291 | 301 | char *key, |
@@ -68,6 +68,7 @@ | ||
68 | 68 | #include "btif_storage.h" |
69 | 69 | #include "btif/include/btif_debug_btsnoop.h" |
70 | 70 | #include "btif/include/btif_debug_conn.h" |
71 | +#include "btif/include/btif_debug_l2c.h" | |
71 | 72 | #include "btif/include/btif_media.h" |
72 | 73 | #include "l2cdefs.h" |
73 | 74 | #include "l2c_api.h" |
@@ -392,20 +393,15 @@ static int read_energy_info() | ||
392 | 393 | static void dump(int fd, const char **arguments) |
393 | 394 | { |
394 | 395 | if (arguments != NULL && arguments[0] != NULL) { |
395 | - if (strncmp(arguments[0], "--proto-text", 12) == 0) { | |
396 | - btif_update_a2dp_metrics(); | |
397 | - metrics_print(fd, true); | |
398 | - return; | |
399 | - } | |
400 | 396 | if (strncmp(arguments[0], "--proto-bin", 11) == 0) { |
401 | - btif_update_a2dp_metrics(); | |
402 | - metrics_write(fd, true); | |
397 | + metrics_write_base64(fd, true); | |
403 | 398 | return; |
404 | 399 | } |
405 | 400 | } |
406 | 401 | btif_debug_conn_dump(fd); |
407 | 402 | btif_debug_bond_event_dump(fd); |
408 | 403 | btif_debug_a2dp_dump(fd); |
404 | + btif_debug_l2c_dump(fd); | |
409 | 405 | btif_debug_config_dump(fd); |
410 | 406 | wakelock_debug_dump(fd); |
411 | 407 | alarm_debug_dump(fd); |
@@ -0,0 +1,159 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2016 Google Inc. | |
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 | + | |
19 | +#include <stdio.h> | |
20 | +#include <stdint.h> | |
21 | +#include <string.h> | |
22 | +#include <time.h> | |
23 | + | |
24 | +#include "btcore/include/bdaddr.h" | |
25 | +#include "btif/include/btif_debug.h" | |
26 | +#include "btif/include/btif_debug_l2c.h" | |
27 | + | |
28 | +#define NUM_UPDATE_REQUESTS 5 | |
29 | +#define NUM_UPDATE_RESPONSES 5 | |
30 | + | |
31 | +#define INTERVAL_1_25_MS_MULTIPLIER 1.25f | |
32 | +#define TIMEOUT_10_MS_MULTIPLIER 10 | |
33 | + | |
34 | +typedef enum { | |
35 | + BTIF_DEBUG_CONNECTION_UPDATE_REQUEST, | |
36 | + BTIF_DEBUG_CONNECTION_UPDATE_RESPONSE, | |
37 | +} btif_debug_ble_conn_update_t; | |
38 | + | |
39 | +/* Shared Connection update record for both request and response. */ | |
40 | +typedef struct ble_conn_update_t { | |
41 | + uint64_t timestamp_ms; | |
42 | + bt_bdaddr_t bda; | |
43 | + btif_debug_ble_conn_update_t type; | |
44 | + uint8_t status; /* Not populated for request. */ | |
45 | + uint16_t min_interval; /* Not populated for response. */ | |
46 | + uint16_t max_interval; | |
47 | + uint16_t latency; | |
48 | + uint16_t timeout; | |
49 | +} ble_conn_update_t; | |
50 | + | |
51 | +static int update_request_index; | |
52 | +static int update_response_index; | |
53 | +static ble_conn_update_t last_ble_conn_update_requests[NUM_UPDATE_REQUESTS]; | |
54 | +static ble_conn_update_t last_ble_conn_update_responses[NUM_UPDATE_RESPONSES]; | |
55 | + | |
56 | +static int dump_connection_update(int fd, const ble_conn_update_t *update) { | |
57 | + if (!update || update->timestamp_ms == 0) { | |
58 | + return -1; | |
59 | + } | |
60 | + | |
61 | + /* Format timestamp */ | |
62 | + const uint64_t msecs = update->timestamp_ms / 1000; | |
63 | + const time_t secs = msecs / 1000; | |
64 | + struct tm *ptm = localtime(&secs); | |
65 | + char time_buf[20] = {0}; | |
66 | + strftime(time_buf, sizeof(time_buf), "%m-%d %H:%M:%S", ptm); | |
67 | + snprintf(time_buf, sizeof(time_buf), "%s.%03u", time_buf, | |
68 | + (uint16_t)(msecs % 1000)); | |
69 | + | |
70 | + /* Format address */ | |
71 | + char addr_buf[18] = {0}; | |
72 | + bdaddr_to_string(&update->bda, addr_buf, sizeof(addr_buf)); | |
73 | + | |
74 | + if (update->type == BTIF_DEBUG_CONNECTION_UPDATE_REQUEST) { | |
75 | + dprintf(fd, | |
76 | + " %s %s min interval=%d (%.2fms) max interval=%d (%.2fms) " | |
77 | + "latency parameter=%d timeout multiplier=%d (%dms)\n", | |
78 | + time_buf, addr_buf, update->min_interval, | |
79 | + (float)update->min_interval * INTERVAL_1_25_MS_MULTIPLIER, | |
80 | + update->max_interval, | |
81 | + (float)update->max_interval * INTERVAL_1_25_MS_MULTIPLIER, | |
82 | + update->latency, update->timeout, | |
83 | + update->timeout * TIMEOUT_10_MS_MULTIPLIER); | |
84 | + } else { | |
85 | + dprintf(fd, | |
86 | + " %s %s status=%d interval=%d (%.2fms) latency parameter=%d " | |
87 | + "timeout multiplier=%d (%dms)\n", time_buf, | |
88 | + addr_buf, update->status, update->max_interval, | |
89 | + (float)update->max_interval * INTERVAL_1_25_MS_MULTIPLIER, | |
90 | + update->latency, update->timeout, | |
91 | + update->timeout * TIMEOUT_10_MS_MULTIPLIER); | |
92 | + } | |
93 | + | |
94 | + return 0; | |
95 | +} | |
96 | + | |
97 | +static void record_connection_update(bt_bdaddr_t bda, uint8_t status, | |
98 | + uint16_t min_interval, uint16_t max_interval, uint16_t latency, | |
99 | + uint16_t timeout, btif_debug_ble_conn_update_t type, | |
100 | + ble_conn_update_t* update) { | |
101 | + | |
102 | + memcpy(&update->bda, &bda, sizeof(bt_bdaddr_t)); | |
103 | + update->type = type; | |
104 | + update->timestamp_ms = btif_debug_ts(); | |
105 | + update->min_interval = min_interval; | |
106 | + update->max_interval = max_interval; | |
107 | + update->latency = latency; | |
108 | + update->timeout = timeout; | |
109 | + update->status = 0; | |
110 | +} | |
111 | + | |
112 | +void btif_debug_ble_connection_update_request(bt_bdaddr_t bda, | |
113 | + uint16_t min_interval, uint16_t max_interval, uint16_t slave_latency_param, | |
114 | + uint16_t timeout_multiplier) { | |
115 | + ble_conn_update_t *request = | |
116 | + &last_ble_conn_update_requests[update_request_index]; | |
117 | + | |
118 | + record_connection_update(bda, 0, min_interval, max_interval, slave_latency_param, | |
119 | + timeout_multiplier, BTIF_DEBUG_CONNECTION_UPDATE_REQUEST, request); | |
120 | + | |
121 | + update_request_index = (update_request_index == NUM_UPDATE_REQUESTS - 1) ? | |
122 | + 0 : update_request_index + 1; | |
123 | +} | |
124 | + | |
125 | +void btif_debug_ble_connection_update_response(bt_bdaddr_t bda, uint8_t status, | |
126 | + uint16_t interval, uint16_t slave_latency_param, | |
127 | + uint16_t timeout_multiplier) { | |
128 | + ble_conn_update_t *response = | |
129 | + &last_ble_conn_update_responses[update_response_index]; | |
130 | + | |
131 | + record_connection_update(bda, status, 0, interval, slave_latency_param, | |
132 | + timeout_multiplier, BTIF_DEBUG_CONNECTION_UPDATE_RESPONSE, response); | |
133 | + | |
134 | + update_response_index = (update_response_index == NUM_UPDATE_RESPONSES - 1) ? | |
135 | + 0 : update_response_index + 1; | |
136 | +} | |
137 | + | |
138 | +void btif_debug_l2c_dump(int fd) { | |
139 | + dprintf(fd, "\nLE Connection Parameter Updates:\n"); | |
140 | + | |
141 | + int i; | |
142 | + dprintf(fd, " Last %d Request(s):\n", NUM_UPDATE_REQUESTS); | |
143 | + for (i = 0; i < NUM_UPDATE_REQUESTS; ++i) { | |
144 | + if (dump_connection_update(fd, &last_ble_conn_update_requests[i]) < 0 && | |
145 | + i == 0) { | |
146 | + dprintf(fd, " None\n"); | |
147 | + break; | |
148 | + } | |
149 | + } | |
150 | + | |
151 | + dprintf(fd, "\n Last %d Response(s):\n", NUM_UPDATE_RESPONSES); | |
152 | + for (i = 0; i < NUM_UPDATE_RESPONSES; ++i) { | |
153 | + if (dump_connection_update(fd, &last_ble_conn_update_responses[i]) < 0 && | |
154 | + i == 0) { | |
155 | + dprintf(fd, " None\n"); | |
156 | + break; | |
157 | + } | |
158 | + } | |
159 | +} |
@@ -230,6 +230,7 @@ static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl); | ||
230 | 230 | static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req); |
231 | 231 | static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) ; |
232 | 232 | static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type); |
233 | +static void btif_dm_ble_sc_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type); | |
233 | 234 | #endif |
234 | 235 | |
235 | 236 | static void bte_scan_filt_param_cfg_evt(UINT8 action_type, |
@@ -818,7 +819,15 @@ static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transpor | ||
818 | 819 | } |
819 | 820 | if (btif_storage_get_remote_addr_type(bd_addr, &addr_type) != BT_STATUS_SUCCESS) |
820 | 821 | { |
821 | - btif_storage_set_remote_addr_type(bd_addr, BLE_ADDR_PUBLIC); | |
822 | + | |
823 | + // Try to read address type. OOB pairing might have set it earlier, but | |
824 | + // didn't store it, it defaults to BLE_ADDR_PUBLIC | |
825 | + uint8_t tmp_dev_type; | |
826 | + uint8_t tmp_addr_type; | |
827 | + BTM_ReadDevInfo(bd_addr->address, &tmp_dev_type, &tmp_addr_type); | |
828 | + addr_type = tmp_addr_type; | |
829 | + | |
830 | + btif_storage_set_remote_addr_type(bd_addr, addr_type); | |
822 | 831 | } |
823 | 832 | } |
824 | 833 | if((btif_config_get_int((char const *)&bdstr,"DevType", &device_type) && |
@@ -1878,7 +1887,7 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) | ||
1878 | 1887 | uint32_t i; |
1879 | 1888 | bt_bdaddr_t bd_addr; |
1880 | 1889 | |
1881 | - BTIF_TRACE_EVENT("btif_dm_upstreams_cback ev: %s", dump_dm_event(event)); | |
1890 | + BTIF_TRACE_EVENT("%s: ev: %s", __func__, dump_dm_event(event)); | |
1882 | 1891 | |
1883 | 1892 | switch (event) |
1884 | 1893 | { |
@@ -2162,6 +2171,10 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) | ||
2162 | 2171 | BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. "); |
2163 | 2172 | btif_dm_ble_oob_req_evt(&p_data->rmt_oob); |
2164 | 2173 | break; |
2174 | + case BTA_DM_BLE_SC_OOB_REQ_EVT: | |
2175 | + BTIF_TRACE_DEBUG("BTA_DM_BLE_SC_OOB_REQ_EVT. "); | |
2176 | + btif_dm_ble_sc_oob_req_evt(&p_data->rmt_oob); | |
2177 | + break; | |
2165 | 2178 | case BTA_DM_BLE_LOCAL_IR_EVT: |
2166 | 2179 | BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. "); |
2167 | 2180 | ble_local_key_cb.is_id_keys_rcvd = TRUE; |
@@ -2630,6 +2643,19 @@ bt_status_t btif_dm_create_bond_out_of_band(const bt_bdaddr_t *bd_addr, int tran | ||
2630 | 2643 | bdcpy(oob_cb.bdaddr, bd_addr->address); |
2631 | 2644 | memcpy(&oob_cb.oob_data, oob_data, sizeof(bt_out_of_band_data_t)); |
2632 | 2645 | |
2646 | + uint8_t empty[] = {0, 0, 0, 0, 0, 0, 0}; | |
2647 | + // If LE Bluetooth Device Address is provided, use provided address type | |
2648 | + // value. | |
2649 | + if (memcmp(oob_data->le_bt_dev_addr, empty, 7) != 0) { | |
2650 | + /* byte no 7 is address type in LE Bluetooth Address OOB data */ | |
2651 | + uint8_t address_type = oob_data->le_bt_dev_addr[6]; | |
2652 | + if (address_type == BLE_ADDR_PUBLIC || address_type == BLE_ADDR_RANDOM) { | |
2653 | + // bd_addr->address is already reversed, so use it instead of | |
2654 | + // oob_data->le_bt_dev_addr | |
2655 | + BTM_SecAddBleDevice(bd_addr->address, NULL, BT_DEVICE_TYPE_BLE, address_type); | |
2656 | + } | |
2657 | + } | |
2658 | + | |
2633 | 2659 | bdstr_t bdstr; |
2634 | 2660 | BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport); |
2635 | 2661 | return btif_dm_create_bond(bd_addr, transport); |
@@ -3102,29 +3128,36 @@ void btif_dm_set_oob_for_le_io_req(BD_ADDR bd_addr, tBTA_OOB_DATA *p_has_oob_da | ||
3102 | 3128 | tBTA_LE_AUTH_REQ *p_auth_req) |
3103 | 3129 | { |
3104 | 3130 | |
3105 | - /* We currently support only Security Manager TK as OOB data for LE transport. | |
3106 | - If it's not present mark no OOB data. | |
3107 | - */ | |
3108 | - if (!is_empty_128bit(oob_cb.oob_data.sm_tk)) | |
3109 | - { | |
3131 | + if (!is_empty_128bit(oob_cb.oob_data.le_sc_c) && | |
3132 | + !is_empty_128bit(oob_cb.oob_data.le_sc_r)) { | |
3133 | + /* We have LE SC OOB data */ | |
3134 | + | |
3135 | + /* make sure OOB data is for this particular device */ | |
3136 | + if (memcmp(bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) == 0) { | |
3137 | + *p_auth_req = ((*p_auth_req) | BTM_LE_AUTH_REQ_SC_ONLY); | |
3138 | + *p_has_oob_data = true; | |
3139 | + } else { | |
3140 | + *p_has_oob_data = false; | |
3141 | + BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address", | |
3142 | + __func__); | |
3143 | + } | |
3144 | + } else if (!is_empty_128bit(oob_cb.oob_data.sm_tk)) { | |
3145 | + /* We have security manager TK */ | |
3146 | + | |
3110 | 3147 | /* make sure OOB data is for this particular device */ |
3111 | 3148 | if (memcmp(bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) == 0) { |
3112 | 3149 | // When using OOB with TK, SC Secure Connections bit must be disabled. |
3113 | 3150 | tBTA_LE_AUTH_REQ mask = ~BTM_LE_AUTH_REQ_SC_ONLY; |
3114 | 3151 | *p_auth_req = ((*p_auth_req) & mask); |
3115 | 3152 | |
3116 | - *p_has_oob_data = TRUE; | |
3117 | - } | |
3118 | - else | |
3119 | - { | |
3120 | - *p_has_oob_data = FALSE; | |
3153 | + *p_has_oob_data = true; | |
3154 | + } else { | |
3155 | + *p_has_oob_data = false; | |
3121 | 3156 | BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address", |
3122 | 3157 | __func__); |
3123 | 3158 | } |
3124 | - } | |
3125 | - else | |
3126 | - { | |
3127 | - *p_has_oob_data = FALSE; | |
3159 | + } else { | |
3160 | + *p_has_oob_data = false; | |
3128 | 3161 | } |
3129 | 3162 | BTIF_TRACE_DEBUG("%s *p_has_oob_data=%d", __func__, *p_has_oob_data); |
3130 | 3163 | } |
@@ -3625,10 +3658,9 @@ static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type) | ||
3625 | 3658 | |
3626 | 3659 | bt_bdaddr_t bd_addr; |
3627 | 3660 | bdcpy(bd_addr.address, req_oob_type->bd_addr); |
3628 | - | |
3629 | - /* We currently support only Security Manager TK as OOB data. We already | |
3630 | - * checked if it's present in btif_dm_set_oob_for_le_io_req, but check here | |
3631 | - * again. If it's not present do nothing, pairing will timeout. | |
3661 | + /* We already checked if OOB data is present in | |
3662 | + * btif_dm_set_oob_for_le_io_req, but check here again. If it's not present | |
3663 | + * do nothing, pairing will timeout. | |
3632 | 3664 | */ |
3633 | 3665 | if (is_empty_128bit(oob_cb.oob_data.sm_tk)) { |
3634 | 3666 | return; |
@@ -3652,6 +3684,44 @@ static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type) | ||
3652 | 3684 | BTM_BleOobDataReply(req_oob_type->bd_addr, 0, 16, oob_cb.oob_data.sm_tk); |
3653 | 3685 | } |
3654 | 3686 | |
3687 | + | |
3688 | +static void btif_dm_ble_sc_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type) | |
3689 | +{ | |
3690 | + BTIF_TRACE_DEBUG("%s", __func__); | |
3691 | + | |
3692 | + bt_bdaddr_t bd_addr; | |
3693 | + bdcpy(bd_addr.address, req_oob_type->bd_addr); | |
3694 | + | |
3695 | + /* We already checked if OOB data is present in | |
3696 | + * btif_dm_set_oob_for_le_io_req, but check here again. If it's not present | |
3697 | + * do nothing, pairing will timeout. | |
3698 | + */ | |
3699 | + if (is_empty_128bit(oob_cb.oob_data.le_sc_c) && | |
3700 | + is_empty_128bit(oob_cb.oob_data.le_sc_r)) { | |
3701 | + BTIF_TRACE_WARNING("%s: LE SC OOB data is empty", __func__); | |
3702 | + return; | |
3703 | + } | |
3704 | + | |
3705 | + /* make sure OOB data is for this particular device */ | |
3706 | + if (memcmp(req_oob_type->bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) != 0) { | |
3707 | + BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address", __func__); | |
3708 | + return; | |
3709 | + } | |
3710 | + | |
3711 | + /* Remote name update */ | |
3712 | + btif_update_remote_properties(req_oob_type->bd_addr , req_oob_type->bd_name, | |
3713 | + NULL, BT_DEVICE_TYPE_BLE); | |
3714 | + | |
3715 | + bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING); | |
3716 | + pairing_cb.is_ssp = false; | |
3717 | + pairing_cb.is_le_only = true; //TODO: we can derive classic pairing from this one | |
3718 | + pairing_cb.is_le_nc = false; | |
3719 | + | |
3720 | + BTM_BleSecureConnectionOobDataReply(req_oob_type->bd_addr, | |
3721 | + oob_cb.oob_data.le_sc_c, | |
3722 | + oob_cb.oob_data.le_sc_r); | |
3723 | +} | |
3724 | + | |
3655 | 3725 | void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name, |
3656 | 3726 | tBT_DEVICE_TYPE dev_type) |
3657 | 3727 | { |
@@ -3797,7 +3867,7 @@ static void btif_stats_add_bond_event(const bt_bdaddr_t *bd_addr, | ||
3797 | 3867 | uint32_t cod = get_cod(bd_addr); |
3798 | 3868 | uint64_t ts = event->timestamp.tv_sec * 1000 + |
3799 | 3869 | event->timestamp.tv_nsec / 1000000; |
3800 | - metrics_pair_event(0, ts, cod, device_type); | |
3870 | + metrics_log_pair_event(0, ts, cod, device_type); | |
3801 | 3871 | |
3802 | 3872 | pthread_mutex_unlock(&bond_event_lock); |
3803 | 3873 | } |
@@ -305,6 +305,7 @@ typedef struct { | ||
305 | 305 | |
306 | 306 | typedef struct { |
307 | 307 | uint64_t session_start_us; |
308 | + uint64_t session_end_us; | |
308 | 309 | |
309 | 310 | scheduling_stats_t tx_queue_enqueue_stats; |
310 | 311 | scheduling_stats_t tx_queue_dequeue_stats; |
@@ -322,6 +323,7 @@ typedef struct { | ||
322 | 323 | uint64_t tx_queue_last_flushed_us; |
323 | 324 | |
324 | 325 | size_t tx_queue_total_dropped_messages; |
326 | + size_t tx_queue_max_dropped_messages; | |
325 | 327 | size_t tx_queue_dropouts; |
326 | 328 | uint64_t tx_queue_last_dropouts_us; |
327 | 329 |
@@ -410,6 +412,7 @@ typedef struct | ||
410 | 412 | BOOLEAN tx_enc_update_initiated; |
411 | 413 | //#endif |
412 | 414 | |
415 | + btif_media_stats_t accumulated_stats; | |
413 | 416 | #endif |
414 | 417 | } tBTIF_MEDIA_CB; |
415 | 418 |
@@ -532,6 +535,68 @@ static uint8_t multicast_query = FALSE; | ||
532 | 535 | /***************************************************************************** |
533 | 536 | ** Misc helper functions |
534 | 537 | *****************************************************************************/ |
538 | +void btif_a2dp_source_accumulate_scheduling_stats(scheduling_stats_t* src, | |
539 | + scheduling_stats_t* dst) { | |
540 | + dst->total_updates += src->total_updates; | |
541 | + dst->last_update_us = src->last_update_us; | |
542 | + dst->overdue_scheduling_count += src->overdue_scheduling_count; | |
543 | + dst->total_overdue_scheduling_delta_us += src->total_overdue_scheduling_delta_us; | |
544 | + if (src->max_overdue_scheduling_delta_us > dst->max_overdue_scheduling_delta_us) { | |
545 | + dst->max_overdue_scheduling_delta_us = src->max_overdue_scheduling_delta_us; | |
546 | + } | |
547 | + dst->premature_scheduling_count += src->premature_scheduling_count; | |
548 | + dst->total_premature_scheduling_delta_us += src->total_premature_scheduling_delta_us; | |
549 | + if (src->max_premature_scheduling_delta_us > dst->max_premature_scheduling_delta_us) { | |
550 | + dst->max_premature_scheduling_delta_us = src->max_premature_scheduling_delta_us; | |
551 | + } | |
552 | + dst->exact_scheduling_count += src->exact_scheduling_count; | |
553 | + dst->total_scheduling_time_us += src->total_scheduling_time_us; | |
554 | +} | |
555 | + | |
556 | +void btif_a2dp_source_accumulate_stats(btif_media_stats_t* src, | |
557 | + btif_media_stats_t* dst) { | |
558 | + dst->tx_queue_total_frames += src->tx_queue_total_frames; | |
559 | + if (src->tx_queue_max_frames_per_packet > dst->tx_queue_max_frames_per_packet) { | |
560 | + dst->tx_queue_max_frames_per_packet = src->tx_queue_max_frames_per_packet; | |
561 | + } | |
562 | + dst->tx_queue_total_queueing_time_us += src->tx_queue_total_queueing_time_us; | |
563 | + if (src->tx_queue_max_queueing_time_us > dst->tx_queue_max_queueing_time_us) { | |
564 | + dst->tx_queue_max_queueing_time_us = src->tx_queue_max_queueing_time_us; | |
565 | + } | |
566 | + dst->tx_queue_total_readbuf_calls += src->tx_queue_total_readbuf_calls; | |
567 | + dst->tx_queue_last_readbuf_us = src->tx_queue_last_readbuf_us; | |
568 | + dst->tx_queue_total_flushed_messages += src->tx_queue_total_flushed_messages; | |
569 | + dst->tx_queue_last_flushed_us = src->tx_queue_last_flushed_us; | |
570 | + dst->tx_queue_total_dropped_messages += src->tx_queue_total_dropped_messages; | |
571 | + if (src->tx_queue_max_dropped_messages > dst->tx_queue_max_dropped_messages) { | |
572 | + dst->tx_queue_max_dropped_messages = src->tx_queue_max_dropped_messages; | |
573 | + } | |
574 | + dst->tx_queue_dropouts += src->tx_queue_dropouts; | |
575 | + dst->tx_queue_last_dropouts_us = src->tx_queue_last_dropouts_us; | |
576 | + dst->media_read_total_underflow_bytes += | |
577 | + src->media_read_total_underflow_bytes; | |
578 | + dst->media_read_total_underflow_count += | |
579 | + src->media_read_total_underflow_count; | |
580 | + dst->media_read_last_underflow_us = src->media_read_last_underflow_us; | |
581 | + dst->media_read_total_underrun_bytes += src->media_read_total_underrun_bytes; | |
582 | + dst->media_read_total_underflow_count += src->media_read_total_underrun_count; | |
583 | + dst->media_read_last_underrun_us = src->media_read_last_underrun_us; | |
584 | + dst->media_read_total_expected_frames += src->media_read_total_expected_frames; | |
585 | + if (src->media_read_max_expected_frames > dst->media_read_max_expected_frames) { | |
586 | + dst->media_read_max_expected_frames = src->media_read_max_expected_frames; | |
587 | + } | |
588 | + dst->media_read_expected_count += src->media_read_expected_count; | |
589 | + dst->media_read_total_limited_frames += src->media_read_total_limited_frames; | |
590 | + if (src->media_read_max_limited_frames > dst->media_read_max_limited_frames) { | |
591 | + dst->media_read_max_limited_frames = src->media_read_max_limited_frames; | |
592 | + } | |
593 | + dst->media_read_limited_count += src->media_read_limited_count; | |
594 | + btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_enqueue_stats, | |
595 | + &dst->tx_queue_enqueue_stats); | |
596 | + btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_dequeue_stats, | |
597 | + &dst->tx_queue_dequeue_stats); | |
598 | + memset(src, 0, sizeof(btif_media_stats_t)); | |
599 | +} | |
535 | 600 | |
536 | 601 | static void update_scheduling_stats(scheduling_stats_t *stats, |
537 | 602 | uint64_t now_us, uint64_t expected_delta) |
@@ -629,7 +694,11 @@ UNUSED_ATTR static const char *dump_media_event(UINT16 event) | ||
629 | 694 | |
630 | 695 | static void btm_read_rssi_cb(void *data) |
631 | 696 | { |
632 | - assert(data); | |
697 | + if (data == NULL) | |
698 | + { | |
699 | + LOG_ERROR(LOG_TAG, "%s RSSI request timed out", __func__); | |
700 | + return; | |
701 | + } | |
633 | 702 | |
634 | 703 | tBTM_RSSI_RESULTS *result = (tBTM_RSSI_RESULTS*)data; |
635 | 704 | if (result->status != BTM_SUCCESS) |
@@ -2027,6 +2096,9 @@ static void btif_media_task_aa_handle_timer(UNUSED_ATTR void *context) | ||
2027 | 2096 | if (alarm_is_scheduled(btif_media_cb.media_alarm)) |
2028 | 2097 | { |
2029 | 2098 | btif_media_send_aa_frame(timestamp_us); |
2099 | + update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats, | |
2100 | + timestamp_us, | |
2101 | + BTIF_SINK_MEDIA_TIME_TICK_MS * 1000); | |
2030 | 2102 | } |
2031 | 2103 | else |
2032 | 2104 | { |
@@ -2054,7 +2126,6 @@ static void btif_media_thread_init(UNUSED_ATTR void *context) { | ||
2054 | 2126 | |
2055 | 2127 | APPL_TRACE_IMP(" btif_media_thread_init"); |
2056 | 2128 | memset(&btif_media_cb, 0, sizeof(btif_media_cb)); |
2057 | - btif_media_cb.stats.session_start_us = time_now_us(); | |
2058 | 2129 | |
2059 | 2130 | UIPC_Init(NULL); |
2060 | 2131 |
@@ -2067,6 +2138,7 @@ static void btif_media_thread_init(UNUSED_ATTR void *context) { | ||
2067 | 2138 | raise_priority_a2dp(TASK_HIGH_MEDIA); |
2068 | 2139 | media_task_running = MEDIA_TASK_STATE_ON; |
2069 | 2140 | APPL_TRACE_DEBUG(" btif_media_thread_init complete"); |
2141 | + metrics_log_bluetooth_session_start(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); | |
2070 | 2142 | } |
2071 | 2143 | |
2072 | 2144 | static void btif_media_thread_cleanup(UNUSED_ATTR void *context) { |
@@ -2085,6 +2157,7 @@ static void btif_media_thread_cleanup(UNUSED_ATTR void *context) { | ||
2085 | 2157 | /* Clear media task flag */ |
2086 | 2158 | media_task_running = MEDIA_TASK_STATE_OFF; |
2087 | 2159 | APPL_TRACE_DEBUG(" btif_media_thread_cleanup complete"); |
2160 | + metrics_log_bluetooth_session_end(DISCONNECT_REASON_UNKNOWN, 0); | |
2088 | 2161 | } |
2089 | 2162 | |
2090 | 2163 | /******************************************************************************* |
@@ -2440,6 +2513,14 @@ BOOLEAN btif_media_task_start_aa_req(void) | ||
2440 | 2513 | |
2441 | 2514 | if (btif_media_cmd_msg_queue != NULL) |
2442 | 2515 | fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); |
2516 | + memset(&btif_media_cb.stats, 0, sizeof(btif_media_stats_t)); | |
2517 | + // Assign session_start_us to 1 when time_now_us() is 0 to indicate | |
2518 | + // btif_media_task_start_aa_req() has been called | |
2519 | + btif_media_cb.stats.session_start_us = time_now_us(); | |
2520 | + if (btif_media_cb.stats.session_start_us == 0) { | |
2521 | + btif_media_cb.stats.session_start_us = 1; | |
2522 | + } | |
2523 | + btif_media_cb.stats.session_end_us = 0; | |
2443 | 2524 | return TRUE; |
2444 | 2525 | } |
2445 | 2526 |
@@ -2468,8 +2549,14 @@ BOOLEAN btif_media_task_stop_aa_req(void) | ||
2468 | 2549 | * the "cleanup() -> btif_a2dp_stop_media_task()" processing during |
2469 | 2550 | * the shutdown of the Bluetooth stack. |
2470 | 2551 | */ |
2471 | - if (btif_media_cmd_msg_queue != NULL) | |
2552 | + if (btif_media_cmd_msg_queue != NULL) { | |
2472 | 2553 | fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf); |
2554 | + } | |
2555 | + | |
2556 | + btif_media_cb.stats.session_end_us = time_now_us(); | |
2557 | + btif_update_a2dp_metrics(); | |
2558 | + btif_a2dp_source_accumulate_stats(&btif_media_cb.stats, | |
2559 | + &btif_media_cb.accumulated_stats); | |
2473 | 2560 | |
2474 | 2561 | return TRUE; |
2475 | 2562 | } |
@@ -4223,9 +4310,6 @@ static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame, | ||
4223 | 4310 | } |
4224 | 4311 | |
4225 | 4312 | /* Enqueue the encoded SBC frame in AA Tx Queue */ |
4226 | - update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats, | |
4227 | - timestamp_us, | |
4228 | - BTIF_SINK_MEDIA_TIME_TICK_MS * 1000); | |
4229 | 4313 | uint8_t done_nb_frame = remain_nb_frame - nb_frame; |
4230 | 4314 | remain_nb_frame = nb_frame; |
4231 | 4315 | btif_media_cb.stats.tx_queue_total_frames += done_nb_frame; |
@@ -4268,6 +4352,10 @@ static void btif_media_aa_prep_2_send(UINT8 nb_frame, uint64_t timestamp_us) | ||
4268 | 4352 | btif_media_cb.stats.tx_queue_last_dropouts_us = timestamp_us; |
4269 | 4353 | |
4270 | 4354 | // Flush all queued buffers... |
4355 | + size_t drop_n = fixed_queue_length(btif_media_cb.TxAaQ); | |
4356 | + if (drop_n > btif_media_cb.stats.tx_queue_max_dropped_messages) { | |
4357 | + btif_media_cb.stats.tx_queue_max_dropped_messages = drop_n; | |
4358 | + } | |
4271 | 4359 | while (fixed_queue_length(btif_media_cb.TxAaQ)) { |
4272 | 4360 | btif_media_cb.stats.tx_queue_total_dropped_messages++; |
4273 | 4361 | osi_free(fixed_queue_try_dequeue(btif_media_cb.TxAaQ)); |
@@ -4945,8 +5033,10 @@ void dump_codec_info(unsigned char *p_codec) | ||
4945 | 5033 | |
4946 | 5034 | void btif_debug_a2dp_dump(int fd) |
4947 | 5035 | { |
5036 | + btif_a2dp_source_accumulate_stats(&btif_media_cb.stats, | |
5037 | + &btif_media_cb.accumulated_stats); | |
4948 | 5038 | uint64_t now_us = time_now_us(); |
4949 | - btif_media_stats_t *stats = &btif_media_cb.stats; | |
5039 | + btif_media_stats_t *stats = &btif_media_cb.accumulated_stats; | |
4950 | 5040 | scheduling_stats_t *enqueue_stats = &stats->tx_queue_enqueue_stats; |
4951 | 5041 | scheduling_stats_t *dequeue_stats = &stats->tx_queue_dequeue_stats; |
4952 | 5042 | size_t ave_size; |
@@ -5080,52 +5170,51 @@ void btif_debug_a2dp_dump(int fd) | ||
5080 | 5170 | |
5081 | 5171 | void btif_update_a2dp_metrics(void) |
5082 | 5172 | { |
5083 | - uint64_t now_us = time_now_us(); | |
5084 | - btif_media_stats_t *stats = &btif_media_cb.stats; | |
5085 | - scheduling_stats_t *dequeue_stats = &stats->tx_queue_dequeue_stats; | |
5086 | - int32_t media_timer_min_ms = 0; | |
5087 | - int32_t media_timer_max_ms = 0; | |
5088 | - int32_t media_timer_avg_ms = 0; | |
5089 | - int32_t buffer_overruns_max_count = 0; | |
5090 | - int32_t buffer_overruns_total = 0; | |
5091 | - float buffer_underruns_average = 0.0; | |
5092 | - int32_t buffer_underruns_count = 0; | |
5093 | - | |
5094 | - int64_t session_duration_sec = | |
5095 | - (now_us - stats->session_start_us) / (1000 * 1000); | |
5096 | - | |
5097 | - /* NOTE: Disconnect reason is unused */ | |
5098 | - const char *disconnect_reason = NULL; | |
5099 | - uint32_t device_class = BTM_COD_MAJOR_AUDIO; | |
5100 | - | |
5101 | - if (dequeue_stats->total_updates > 1) { | |
5102 | - media_timer_min_ms = BTIF_SINK_MEDIA_TIME_TICK_MS - | |
5103 | - (dequeue_stats->max_premature_scheduling_delta_us / 1000); | |
5104 | - media_timer_max_ms = BTIF_SINK_MEDIA_TIME_TICK_MS + | |
5105 | - (dequeue_stats->max_overdue_scheduling_delta_us / 1000); | |
5106 | - | |
5107 | - uint64_t total_scheduling_count = | |
5108 | - dequeue_stats->overdue_scheduling_count + | |
5109 | - dequeue_stats->premature_scheduling_count + | |
5110 | - dequeue_stats->exact_scheduling_count; | |
5111 | - if (total_scheduling_count > 0) { | |
5112 | - media_timer_avg_ms = dequeue_stats->total_scheduling_time_us / | |
5113 | - (1000 * total_scheduling_count); | |
5173 | + btif_media_stats_t* stats = &btif_media_cb.stats; | |
5174 | + scheduling_stats_t* enqueue_stats = &stats->tx_queue_enqueue_stats; | |
5175 | + A2dpSessionMetrics_t metrics; | |
5176 | + metrics.media_timer_min_ms = -1; | |
5177 | + metrics.media_timer_max_ms = -1; | |
5178 | + metrics.media_timer_avg_ms = -1; | |
5179 | + metrics.total_scheduling_count = -1; | |
5180 | + metrics.buffer_overruns_max_count = -1; | |
5181 | + metrics.buffer_overruns_total = -1; | |
5182 | + metrics.buffer_underruns_average = -1.0; | |
5183 | + metrics.buffer_underruns_count = -1; | |
5184 | + metrics.audio_duration_ms = -1; | |
5185 | + // session_start_us is 0 when btif_media_task_start_aa_req() is not called | |
5186 | + // mark the metric duration as invalid (-1) in this case | |
5187 | + if (stats->session_start_us != 0) { | |
5188 | + int64_t session_end_us = stats->session_end_us == 0 | |
5189 | + ? time_now_us() | |
5190 | + : stats->session_end_us; | |
5191 | + metrics.audio_duration_ms = (session_end_us - stats->session_start_us) / 1000; | |
5192 | + } | |
5193 | + if (enqueue_stats->total_updates > 1) { | |
5194 | + metrics.media_timer_min_ms = BTIF_SINK_MEDIA_TIME_TICK_MS - | |
5195 | + (enqueue_stats->max_premature_scheduling_delta_us / 1000); | |
5196 | + metrics.media_timer_max_ms = BTIF_SINK_MEDIA_TIME_TICK_MS + | |
5197 | + (enqueue_stats->max_overdue_scheduling_delta_us / 1000); | |
5198 | + metrics.total_scheduling_count | |
5199 | + = enqueue_stats->overdue_scheduling_count + | |
5200 | + enqueue_stats->premature_scheduling_count + | |
5201 | + enqueue_stats->exact_scheduling_count; | |
5202 | + if (metrics.total_scheduling_count > 0) { | |
5203 | + metrics.media_timer_avg_ms = enqueue_stats->total_scheduling_time_us / | |
5204 | + (1000 * metrics.total_scheduling_count); | |
5114 | 5205 | } |
5115 | - | |
5116 | - buffer_overruns_max_count = stats->media_read_max_expected_frames; | |
5117 | - buffer_overruns_total = stats->tx_queue_total_dropped_messages; | |
5118 | - buffer_underruns_count = stats->media_read_total_underflow_count + | |
5119 | - stats->media_read_total_underrun_count; | |
5120 | - if (buffer_underruns_count > 0) { | |
5121 | - buffer_underruns_average = | |
5122 | - (stats->media_read_total_underflow_bytes + stats->media_read_total_underrun_bytes) / buffer_underruns_count; | |
5206 | + metrics.buffer_overruns_max_count = stats->tx_queue_max_dropped_messages; | |
5207 | + metrics.buffer_overruns_total = stats->tx_queue_total_dropped_messages; | |
5208 | + metrics.buffer_underruns_count = | |
5209 | + stats->media_read_total_underflow_count + | |
5210 | + stats->media_read_total_underrun_count; | |
5211 | + metrics.buffer_underruns_average = 0; | |
5212 | + if (metrics.buffer_underruns_count > 0) { | |
5213 | + metrics.buffer_underruns_average = | |
5214 | + (stats->media_read_total_underflow_bytes + | |
5215 | + stats->media_read_total_underrun_bytes) / | |
5216 | + metrics.buffer_underruns_count; | |
5123 | 5217 | } |
5124 | 5218 | } |
5125 | - | |
5126 | - metrics_a2dp_session(session_duration_sec, disconnect_reason, device_class, | |
5127 | - media_timer_min_ms, media_timer_max_ms, | |
5128 | - media_timer_avg_ms, buffer_overruns_max_count, | |
5129 | - buffer_overruns_total, buffer_underruns_average, | |
5130 | - buffer_underruns_count); | |
5219 | + metrics_log_a2dp_session(&metrics); | |
5131 | 5220 | } |
@@ -1447,6 +1447,21 @@ bt_status_t btif_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr) | ||
1447 | 1447 | |
1448 | 1448 | /******************************************************************************* |
1449 | 1449 | ** |
1450 | +** Function btif_storage_get_num_bonded_devices | |
1451 | +** | |
1452 | +** Description BTIF storage API - Gets the number of bonded devices | |
1453 | +** | |
1454 | +** Returns the number of bonded devices | |
1455 | +** | |
1456 | +*******************************************************************************/ | |
1457 | +int btif_storage_get_num_bonded_devices(void) { | |
1458 | + btif_bonded_devices_t bonded_devices; | |
1459 | + btif_in_fetch_bonded_devices(&bonded_devices, 0); | |
1460 | + return bonded_devices.num_devices; | |
1461 | +} | |
1462 | + | |
1463 | +/******************************************************************************* | |
1464 | +** | |
1450 | 1465 | ** Function btif_storage_read_hl_apps_cb |
1451 | 1466 | ** |
1452 | 1467 | ** Description BTIF storage API - Read HL application control block from NVRAM |
@@ -9,7 +9,7 @@ BtSnoopLogOutput=false | ||
9 | 9 | BtSnoopExtDump=false |
10 | 10 | |
11 | 11 | # BtSnoop log output file |
12 | -BtSnoopFileName=/sdcard/btsnoop_hci.log | |
12 | +BtSnoopFileName=/data/misc/bluetooth/logs/btsnoop_hci.log | |
13 | 13 | |
14 | 14 | # Preserve existing BtSnoop log before overwriting |
15 | 15 | BtSnoopSaveLog=false |
@@ -205,12 +205,15 @@ static void update_logging() { | ||
205 | 205 | LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__, log_path, last_log_path, strerror(errno)); |
206 | 206 | } |
207 | 207 | |
208 | + mode_t prevmask = umask(0); | |
208 | 209 | logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); |
209 | 210 | if (logfile_fd == INVALID_FD) { |
210 | 211 | LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path, strerror(errno)); |
211 | 212 | is_logging = false; |
213 | + umask(prevmask); | |
212 | 214 | return; |
213 | 215 | } |
216 | + umask(prevmask); | |
214 | 217 | |
215 | 218 | write(logfile_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16); |
216 | 219 | } else { |
@@ -1684,4 +1684,15 @@ The maximum number of payload octets that the local device can receive in a sing | ||
1684 | 1684 | |
1685 | 1685 | #include "bt_trace.h" |
1686 | 1686 | |
1687 | +/****************************************************************************** | |
1688 | +** | |
1689 | +** Wear | |
1690 | +** | |
1691 | +******************************************************************************/ | |
1692 | + | |
1693 | +/* Enable/disable LE IO capability overriding to no-input-no-output on first bond */ | |
1694 | +#ifndef WEAR_LE_IO_CAP_OVERRIDE | |
1695 | +#define WEAR_LE_IO_CAP_OVERRIDE FALSE | |
1696 | +#endif | |
1697 | + | |
1687 | 1698 | #endif /* BT_TARGET_H */ |
@@ -82,7 +82,8 @@ EXPORT_SYMBOL const module_t stack_config_module = { | ||
82 | 82 | // Interface functions |
83 | 83 | |
84 | 84 | static const char *get_btsnoop_log_path(void) { |
85 | - return config_get_string(config, CONFIG_DEFAULT_SECTION, BTSNOOP_LOG_PATH_KEY, "/data/misc/bluedroid/btsnoop_hci.log"); | |
85 | + return config_get_string(config, CONFIG_DEFAULT_SECTION, BTSNOOP_LOG_PATH_KEY, | |
86 | + "/data/misc/bluetooth/logs/btsnoop_hci.log"); | |
86 | 87 | } |
87 | 88 | |
88 | 89 | static bool get_btsnoop_turned_on(void) { |
@@ -68,7 +68,9 @@ btosiCommonTestSrc := \ | ||
68 | 68 | ./test/future_test.cpp \ |
69 | 69 | ./test/hash_map_test.cpp \ |
70 | 70 | ./test/hash_map_utils_test.cpp \ |
71 | + ./test/leaky_bonded_queue_test.cpp \ | |
71 | 72 | ./test/list_test.cpp \ |
73 | + ./test/metrics_test.cpp \ | |
72 | 74 | ./test/properties_test.cpp \ |
73 | 75 | ./test/rand_test.cpp \ |
74 | 76 | ./test/reactor_test.cpp \ |
@@ -79,6 +81,7 @@ btosiCommonTestSrc := \ | ||
79 | 81 | |
80 | 82 | btosiCommonIncludes := \ |
81 | 83 | $(LOCAL_PATH)/.. \ |
84 | + $(LOCAL_PATH)/../include \ | |
82 | 85 | $(LOCAL_PATH)/../utils/include \ |
83 | 86 | $(LOCAL_PATH)/../stack/include \ |
84 | 87 | $(bluetooth_C_INCLUDES) |
@@ -167,7 +170,7 @@ LOCAL_SRC_FILES := $(btosiCommonTestSrc) | ||
167 | 170 | LOCAL_MODULE := net_test_osi |
168 | 171 | LOCAL_MODULE_TAGS := tests |
169 | 172 | LOCAL_SHARED_LIBRARIES := libc liblog libprotobuf-cpp-full libchrome libcutils |
170 | -LOCAL_STATIC_LIBRARIES := libosi libbt-protos | |
173 | +LOCAL_STATIC_LIBRARIES := libosi libbt-protos libgmock | |
171 | 174 | |
172 | 175 | LOCAL_CFLAGS += $(bluetooth_CFLAGS) |
173 | 176 | LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS) |
@@ -185,7 +188,7 @@ LOCAL_LDLIBS := -lrt -lpthread | ||
185 | 188 | LOCAL_MODULE := net_test_osi |
186 | 189 | LOCAL_MODULE_TAGS := tests |
187 | 190 | LOCAL_SHARED_LIBRARIES := liblog libprotobuf-cpp-full libchrome |
188 | -LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos | |
191 | +LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos libgmock_host | |
189 | 192 | |
190 | 193 | LOCAL_CFLAGS += $(bluetooth_CFLAGS) -DOS_GENERIC |
191 | 194 | LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS) |
@@ -71,7 +71,9 @@ executable("net_test_osi") { | ||
71 | 71 | "test/future_test.cpp", |
72 | 72 | "test/hash_map_test.cpp", |
73 | 73 | "test/hash_map_utils_test.cpp", |
74 | + "test/leaky_bonded_queue_test.cpp", | |
74 | 75 | "test/list_test.cpp", |
76 | + "test/metrics_test.cpp", | |
75 | 77 | "test/properties_test.cpp", |
76 | 78 | "test/rand_test.cpp", |
77 | 79 | "test/reactor_test.cpp", |
@@ -88,6 +90,8 @@ executable("net_test_osi") { | ||
88 | 90 | deps = [ |
89 | 91 | "//osi", |
90 | 92 | "//third_party/googletest:gtest_main", |
93 | + "//third_party/googletest:gmock_main", | |
94 | + "//third_party/libchrome:base", | |
91 | 95 | ] |
92 | 96 | |
93 | 97 | libs = [ |
@@ -0,0 +1,158 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2016 Google, Inc. | |
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 | +#pragma once | |
19 | + | |
20 | +#include <memory> | |
21 | +#include <mutex> | |
22 | +#include <queue> | |
23 | + | |
24 | +namespace system_bt_osi { | |
25 | + | |
26 | +/* | |
27 | + * LeakyBondedQueue<T> | |
28 | + * | |
29 | + * - LeakyLondedQueue<T> is a fixed size queue that leaks oldest item when | |
30 | + * reaching its capacity. This is useful in creating memory bonded data | |
31 | + * structure where freshness is more important than full coverage. | |
32 | + * - The queue is protected by a simple mutex and is thread-safe, although | |
33 | + * improvements could be made to lock enqueue and dequeue separately, it | |
34 | + * is not implemented at this moment due to lack of demand | |
35 | + * - The queue uses unique_ptr to automatically free its content when it is | |
36 | + * destructed. It is the user's responsibility to implement T's destructor | |
37 | + * correctly. | |
38 | + * | |
39 | + */ | |
40 | +template <class T> | |
41 | +class LeakyBondedQueue { | |
42 | + public: | |
43 | + LeakyBondedQueue(size_t capacity); | |
44 | + /* Default destructor | |
45 | + * | |
46 | + * Call Clear() and free the queue structure itself | |
47 | + */ | |
48 | + ~LeakyBondedQueue(); | |
49 | + /* | |
50 | + * Add item NEW_ITEM to the underlining queue. If the queue is full, pop | |
51 | + * the oldest item | |
52 | + */ | |
53 | + void Enqueue(T* new_item); | |
54 | + /* | |
55 | + * Add item NEW_ITEM to the underlining queue. If the queue is full, dequeue | |
56 | + * the oldest item and returns it to the caller. Return nullptr otherwise. | |
57 | + */ | |
58 | + T* EnqueueWithPop(T* new_item); | |
59 | + /* | |
60 | + * Dequeues the oldest item from the queue. Return nullptr if queue is empty | |
61 | + */ | |
62 | + T* Dequeue(); | |
63 | + /* | |
64 | + * Returns the length of queue | |
65 | + */ | |
66 | + size_t Length(); | |
67 | + /* | |
68 | + * Returns the defined capacity of the queue | |
69 | + */ | |
70 | + size_t Capacity(); | |
71 | + /* | |
72 | + * Returns whether the queue is empty | |
73 | + */ | |
74 | + bool Empty(); | |
75 | + /* | |
76 | + * Pops all items from the queue | |
77 | + */ | |
78 | + void Clear(); | |
79 | + | |
80 | + private: | |
81 | + // Put item in unique_ptr so that they get freed automatically when poped or | |
82 | + // when queue_ is freed | |
83 | + std::queue<std::unique_ptr<T>> queue_; | |
84 | + std::mutex lock_; | |
85 | + size_t capacity_; | |
86 | +}; | |
87 | + | |
88 | +/* | |
89 | +* Definitions must be in the header for template classes | |
90 | +*/ | |
91 | + | |
92 | +template <class T> | |
93 | +LeakyBondedQueue<T>::LeakyBondedQueue(size_t capacity) { | |
94 | + capacity_ = capacity; | |
95 | +} | |
96 | + | |
97 | +template <class T> | |
98 | +LeakyBondedQueue<T>::~LeakyBondedQueue() {} | |
99 | + | |
100 | +template <class T> | |
101 | +void LeakyBondedQueue<T>::Enqueue(T* new_item) { | |
102 | + std::lock_guard<std::mutex> lock(lock_); | |
103 | + if ((queue_.size() + 1) > capacity_) { | |
104 | + queue_.pop(); | |
105 | + } | |
106 | + std::unique_ptr<T> item_ptr(new_item); | |
107 | + queue_.push(std::move(item_ptr)); | |
108 | +} | |
109 | + | |
110 | +template <class T> | |
111 | +T* LeakyBondedQueue<T>::EnqueueWithPop(T* new_item) { | |
112 | + std::lock_guard<std::mutex> lock(lock_); | |
113 | + T* old_item = nullptr; | |
114 | + if ((queue_.size() + 1) > capacity_) { | |
115 | + std::unique_ptr<T> item = std::move(queue_.front()); | |
116 | + queue_.pop(); | |
117 | + old_item = item.release(); | |
118 | + } | |
119 | + std::unique_ptr<T> item_ptr(new_item); | |
120 | + queue_.push(std::move(item_ptr)); | |
121 | + return old_item; | |
122 | +} | |
123 | + | |
124 | +template <class T> | |
125 | +T* LeakyBondedQueue<T>::Dequeue() { | |
126 | + std::lock_guard<std::mutex> lock(lock_); | |
127 | + std::unique_ptr<T> item = std::move(queue_.front()); | |
128 | + queue_.pop(); | |
129 | + return item.release(); | |
130 | +} | |
131 | + | |
132 | +template <class T> | |
133 | +void LeakyBondedQueue<T>::Clear() { | |
134 | + std::lock_guard<std::mutex> lock(lock_); | |
135 | + while (!queue_.empty()) { | |
136 | + // unique_ptr does not need to be freed | |
137 | + queue_.pop(); | |
138 | + } | |
139 | +} | |
140 | + | |
141 | +template <class T> | |
142 | +size_t LeakyBondedQueue<T>::Length() { | |
143 | + std::lock_guard<std::mutex> lock(lock_); | |
144 | + return queue_.size(); | |
145 | +} | |
146 | + | |
147 | +template <class T> | |
148 | +size_t LeakyBondedQueue<T>::Capacity() { | |
149 | + return capacity_; | |
150 | +} | |
151 | + | |
152 | +template <class T> | |
153 | +bool LeakyBondedQueue<T>::Empty() { | |
154 | + std::lock_guard<std::mutex> lock(lock_); | |
155 | + return queue_.empty(); | |
156 | +} | |
157 | + | |
158 | +} // namespace system_bt_osi |
@@ -20,6 +20,11 @@ | ||
20 | 20 | |
21 | 21 | #include <stdint.h> |
22 | 22 | |
23 | +#ifdef __cplusplus | |
24 | +extern "C" { | |
25 | +#endif | |
26 | +// Typedefs to hide protobuf definition to the rest of stack | |
27 | + | |
23 | 28 | typedef enum { |
24 | 29 | DEVICE_TYPE_UNKNOWN, |
25 | 30 | DEVICE_TYPE_BREDR, |
@@ -27,26 +32,12 @@ typedef enum { | ||
27 | 32 | DEVICE_TYPE_DUMO, |
28 | 33 | } device_type_t; |
29 | 34 | |
30 | -// Record a pairing event at Unix epoch time |timestamp_ms| | |
31 | -// |device_class| and |device_type| denote the type of device paired. | |
32 | -// |disconnect_reason| is the HCI reason for pairing disconnection, | |
33 | -// see stack/include/hcidefs.h | |
34 | -void metrics_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
35 | - uint32_t device_class, device_type_t device_type); | |
36 | - | |
37 | 35 | typedef enum { |
38 | 36 | WAKE_EVENT_UNKNOWN, |
39 | 37 | WAKE_EVENT_ACQUIRED, |
40 | 38 | WAKE_EVENT_RELEASED, |
41 | 39 | } wake_event_type_t; |
42 | 40 | |
43 | -// Record a wake event at Unix epoch time |timestamp_ms|. | |
44 | -// |type| specifies whether it was acquired or relased, | |
45 | -// |requestor| if provided is the service requesting the wake lock. | |
46 | -// |name| is the name of the wake lock held. | |
47 | -void metrics_wake_event(wake_event_type_t type, const char *requestor, | |
48 | - const char *name, uint64_t timestamp_ms); | |
49 | - | |
50 | 41 | typedef enum { |
51 | 42 | SCAN_TYPE_UNKNOWN, |
52 | 43 | SCAN_TECH_TYPE_LE, |
@@ -54,44 +45,52 @@ typedef enum { | ||
54 | 45 | SCAN_TECH_TYPE_BOTH, |
55 | 46 | } scan_tech_t; |
56 | 47 | |
57 | -// Record a scan event at Unix epoch time |timestamp_ms|. | |
58 | -// |start| is true if this is the beginning of the scan. | |
59 | -// |initiator| is a unique ID identifying the app starting the scan. | |
60 | -// |type| is whether the scan reports BR/EDR, LE, or both. | |
61 | -// |results| is the number of results to be reported. | |
62 | -void metrics_scan_event(bool start, const char *initator, scan_tech_t type, | |
63 | - uint32_t results, uint64_t timestamp_ms); | |
64 | - | |
65 | -// Record A2DP session information. | |
66 | -// |session_duration_sec| is the session duration (in seconds). | |
67 | -// |device_class| is the device class of the paired device. | |
68 | -// |media_timer_min_ms| is the minimum scheduled time (in milliseconds) | |
69 | -// of the media timer. | |
70 | -// |media_timer_max_ms| is the maximum scheduled time (in milliseconds) | |
71 | -// of the media timer. | |
72 | -// |media_timer_avg_ms| is the average scheduled time (in milliseconds) | |
73 | -// of the media timer. | |
74 | -// |buffer_overruns_max_count| - TODO - not clear what this is. | |
75 | -// |buffer_overruns_total| is the number of times the media buffer with | |
76 | -// audio data has overrun. | |
77 | -// |buffer_underruns_average| - TODO - not clear what this is. | |
78 | -// |buffer_underruns_count| is the number of times there was no enough | |
79 | -// audio data to add to the media buffer. | |
80 | -void metrics_a2dp_session(int64_t session_duration_sec, | |
81 | - const char *disconnect_reason, | |
82 | - uint32_t device_class, | |
83 | - int32_t media_timer_min_ms, | |
84 | - int32_t media_timer_max_ms, | |
85 | - int32_t media_timer_avg_ms, | |
86 | - int32_t buffer_overruns_max_count, | |
87 | - int32_t buffer_overruns_total, | |
88 | - float buffer_underruns_average, | |
89 | - int32_t buffer_underruns_count); | |
90 | - | |
91 | -// Writes the metrics, in packed protobuf format, into the descriptor |fd|. | |
92 | -// If |clear| is true, metrics events are cleared afterwards. | |
93 | -void metrics_write(int fd, bool clear); | |
94 | - | |
95 | -// Writes the metrics, in human-readable protobuf format, into the descriptor | |
96 | -// |fd|. If |clear| is true, metrics events are cleared afterwards. | |
97 | -void metrics_print(int fd, bool clear); | |
48 | +typedef enum { | |
49 | + CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, | |
50 | + CONNECTION_TECHNOLOGY_TYPE_LE, | |
51 | + CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
52 | +} connection_tech_t; | |
53 | + | |
54 | +typedef enum { | |
55 | + DISCONNECT_REASON_UNKNOWN, | |
56 | + DISCONNECT_REASON_METRICS_DUMP, | |
57 | + DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS, | |
58 | +} disconnect_reason_t; | |
59 | + | |
60 | +typedef struct { | |
61 | + int64_t audio_duration_ms; | |
62 | + int32_t media_timer_min_ms; | |
63 | + int32_t media_timer_max_ms; | |
64 | + int32_t media_timer_avg_ms; | |
65 | + int64_t total_scheduling_count; | |
66 | + int32_t buffer_overruns_max_count; | |
67 | + int32_t buffer_overruns_total; | |
68 | + float buffer_underruns_average; | |
69 | + int32_t buffer_underruns_count; | |
70 | +} A2dpSessionMetrics_t; | |
71 | + | |
72 | +void metrics_log_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
73 | + uint32_t device_class, device_type_t device_type); | |
74 | + | |
75 | +void metrics_log_wake_event(wake_event_type_t type, const char* requestor, | |
76 | + const char* name, uint64_t timestamp_ms); | |
77 | + | |
78 | +void metrics_log_scan_event(bool start, const char* initator, scan_tech_t type, | |
79 | + uint32_t results, uint64_t timestamp_ms); | |
80 | + | |
81 | +void metrics_log_bluetooth_session_start(connection_tech_t connection_tech_type, | |
82 | + uint64_t timestamp_ms); | |
83 | + | |
84 | +void metrics_log_bluetooth_session_end(disconnect_reason_t disconnect_reason, | |
85 | + uint64_t timestamp_ms); | |
86 | + | |
87 | +void metrics_log_bluetooth_session_device_info(uint32_t device_class, | |
88 | + device_type_t device_type); | |
89 | + | |
90 | +void metrics_log_a2dp_session(A2dpSessionMetrics_t* metrics); | |
91 | + | |
92 | +void metrics_write_base64(int fd, bool clear); | |
93 | + | |
94 | +#ifdef __cplusplus | |
95 | +} | |
96 | +#endif |
@@ -0,0 +1,230 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2016 Google, Inc. | |
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 | +#include <stdint.h> | |
19 | +#include <memory> | |
20 | +#include <string> | |
21 | + | |
22 | +namespace system_bt_osi { | |
23 | + | |
24 | +/* Values of A2DP metrics that we care about | |
25 | + * | |
26 | + * audio_duration_ms : sum of audio duration (in milliseconds). | |
27 | + * device_class: device class of the paired device. | |
28 | + * media_timer_min_ms : minimum scheduled time (in milliseconds) | |
29 | + * of the media timer. | |
30 | + * media_timer_max_ms: maximum scheduled time (in milliseconds) | |
31 | + * of the media timer. | |
32 | + * media_timer_avg_ms: average scheduled time (in milliseconds) | |
33 | + * of the media timer. | |
34 | + * buffer_overruns_max_count: TODO - not clear what this is. | |
35 | + * buffer_overruns_total : number of times the media buffer with | |
36 | + * audio data has overrun | |
37 | + * buffer_underruns_average: TODO - not clear what this is. | |
38 | + * buffer_underruns_count: number of times there was no enough | |
39 | + * audio data to add to the media buffer. | |
40 | + * NOTE: Negative values are invalid | |
41 | +*/ | |
42 | +class A2dpSessionMetrics { | |
43 | + public: | |
44 | + A2dpSessionMetrics() {} | |
45 | + | |
46 | + /* | |
47 | + * Update the metrics value in the current metrics object using the metrics | |
48 | + * objects supplied | |
49 | + */ | |
50 | + void Update(const A2dpSessionMetrics& metrics); | |
51 | + | |
52 | + /* | |
53 | + * Compare whether two metrics objects are equal | |
54 | + */ | |
55 | + bool operator==(const A2dpSessionMetrics& rhs) const; | |
56 | + | |
57 | + /* | |
58 | + * Initialize all values to -1 which is invalid in order to make a distinction | |
59 | + * between 0 and invalid values | |
60 | + */ | |
61 | + int64_t audio_duration_ms = -1; | |
62 | + int32_t media_timer_min_ms = -1; | |
63 | + int32_t media_timer_max_ms = -1; | |
64 | + int32_t media_timer_avg_ms = -1; | |
65 | + int64_t total_scheduling_count = -1; | |
66 | + int32_t buffer_overruns_max_count = -1; | |
67 | + int32_t buffer_overruns_total = -1; | |
68 | + float buffer_underruns_average = -1; | |
69 | + int32_t buffer_underruns_count = -1; | |
70 | +}; | |
71 | + | |
72 | +class BluetoothMetricsLogger { | |
73 | + public: | |
74 | + static BluetoothMetricsLogger* GetInstance() { | |
75 | + static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger(); | |
76 | + return instance; | |
77 | + } | |
78 | + | |
79 | + /* | |
80 | + * Record a pairing event | |
81 | + * | |
82 | + * Parameters: | |
83 | + * timestamp_ms: Unix epoch time in milliseconds | |
84 | + * device_class: class of remote device | |
85 | + * device_type: type of remote device | |
86 | + * disconnect_reason: HCI reason for pairing disconnection. | |
87 | + * See: stack/include/hcidefs.h | |
88 | + */ | |
89 | + void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
90 | + uint32_t device_class, device_type_t device_type); | |
91 | + | |
92 | + /* | |
93 | + * Record a wake event | |
94 | + * | |
95 | + * Parameters: | |
96 | + * timestamp_ms: Unix epoch time in milliseconds | |
97 | + * type: whether it was acquired or released | |
98 | + * requestor: if provided is the service requesting the wake lock | |
99 | + * name: the name of the wake lock held | |
100 | + */ | |
101 | + void LogWakeEvent(wake_event_type_t type, const std::string& requestor, | |
102 | + const std::string& name, uint64_t timestamp_ms); | |
103 | + | |
104 | + /* | |
105 | + * Record a scan event | |
106 | + * | |
107 | + * Parameters | |
108 | + * timestamp_ms : Unix epoch time in milliseconds | |
109 | + * start : true if this is the beginning of the scan | |
110 | + * initiator: a unique ID identifying the app starting the scan | |
111 | + * type: whether the scan reports BR/EDR, LE, or both. | |
112 | + * results: number of results to be reported. | |
113 | + */ | |
114 | + void LogScanEvent(bool start, const std::string& initator, scan_tech_t type, | |
115 | + uint32_t results, uint64_t timestamp_ms); | |
116 | + | |
117 | + /* | |
118 | + * Start logging a Bluetooth session | |
119 | + * | |
120 | + * A Bluetooth session is defined a a connection between this device and | |
121 | + * another remote device which may include multiple profiles and protocols | |
122 | + * | |
123 | + * Only one Bluetooth session can exist at one time. Calling this method twice | |
124 | + * without LogBluetoothSessionEnd will result in logging a premature end of | |
125 | + * current Bluetooth session | |
126 | + * | |
127 | + * Parameters: | |
128 | + * connection_tech_type : type of connection technology | |
129 | + * timestamp_ms : the timestamp for session start, 0 means now | |
130 | + * | |
131 | + */ | |
132 | + void LogBluetoothSessionStart(connection_tech_t connection_tech_type, | |
133 | + uint64_t timestamp_ms); | |
134 | + | |
135 | + /* | |
136 | + * Stop logging a Bluetooth session and pushes it to the log queue | |
137 | + * | |
138 | + * If no Bluetooth session exist, this method exits immediately | |
139 | + * | |
140 | + * Parameters: | |
141 | + * disconnect_reason : A string representation of disconnect reason | |
142 | + * timestamp_ms : the timestamp of session end, 0 means now | |
143 | + * | |
144 | + */ | |
145 | + void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason, | |
146 | + uint64_t timestamp_ms); | |
147 | + | |
148 | + /* | |
149 | + * Log information about remote device in a current Bluetooth session | |
150 | + * | |
151 | + * If a Bluetooth session does not exist, create one with default parameter | |
152 | + * and timestamp now | |
153 | + * | |
154 | + * Parameters: | |
155 | + * device_class : device_class defined in btm_api_types.h | |
156 | + * device_type : type of remote device | |
157 | + */ | |
158 | + void LogBluetoothSessionDeviceInfo(uint32_t device_class, | |
159 | + device_type_t device_type); | |
160 | + | |
161 | + /* | |
162 | + * Log A2DP Audio Session Information | |
163 | + * | |
164 | + * - Repeated calls to this method will override previous metrics if in the | |
165 | + * same Bluetooth connection | |
166 | + * - If a Bluetooth session does not exist, create one with default parameter | |
167 | + * and timestamp now | |
168 | + * | |
169 | + * Parameters: | |
170 | + * a2dp_session_metrics - pointer to struct holding a2dp stats | |
171 | + * | |
172 | + */ | |
173 | + void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics); | |
174 | + | |
175 | + /* | |
176 | + * Writes the metrics, in base64 protobuf format, into the descriptor FD | |
177 | + * If CLEAR is true, metrics events are cleared afterwards. | |
178 | + */ | |
179 | + void WriteBase64(int fd, bool clear); | |
180 | + void WriteBase64String(std::string* serialized, bool clear); | |
181 | + void WriteString(std::string* serialized, bool clear); | |
182 | + | |
183 | + /* | |
184 | + * Reset the metrics logger by cleaning up its staging queues and existing | |
185 | + * protobuf objects. | |
186 | + */ | |
187 | + void Reset(); | |
188 | + | |
189 | + /* | |
190 | + * Maximum number of log entries for each session or event | |
191 | + */ | |
192 | + static const size_t kMaxNumBluetoothSession = 50; | |
193 | + static const size_t kMaxNumPairEvent = 50; | |
194 | + static const size_t kMaxNumWakeEvent = 1000; | |
195 | + static const size_t kMaxNumScanEvent = 50; | |
196 | + | |
197 | + private: | |
198 | + BluetoothMetricsLogger(); | |
199 | + | |
200 | + /* | |
201 | + * When a Bluetooth session is on and the user initiates a metrics dump, we | |
202 | + * need to be able to upload whatever we have first. This method breaks the | |
203 | + * ongoing Bluetooth session into two sessions with the previous one labeled | |
204 | + * as "METRICS_DUMP" for the disconnect reason. | |
205 | + */ | |
206 | + void CutoffSession(); | |
207 | + | |
208 | + /* | |
209 | + * Build the internal metrics object using information gathered | |
210 | + */ | |
211 | + void Build(); | |
212 | + | |
213 | + /* | |
214 | + * Reset objects related to current Bluetooth session | |
215 | + */ | |
216 | + void ResetSession(); | |
217 | + | |
218 | + /* | |
219 | + * Reset the underlining BluetoothLog object | |
220 | + */ | |
221 | + void ResetLog(); | |
222 | + | |
223 | + /* | |
224 | + * PIMPL style implementation to hide internal dependencies | |
225 | + */ | |
226 | + struct impl; | |
227 | + std::unique_ptr<impl> const pimpl_; | |
228 | +}; | |
229 | + | |
230 | +} // namespace system_bt_osi |
@@ -15,28 +15,37 @@ | ||
15 | 15 | * limitations under the License. |
16 | 16 | * |
17 | 17 | ******************************************************************************/ |
18 | - | |
19 | - | |
20 | 18 | #define LOG_TAG "bt_osi_metrics" |
21 | 19 | |
22 | -extern "C" { | |
23 | -#include "osi/include/metrics.h" | |
20 | +#include <unistd.h> | |
21 | +#include <algorithm> | |
22 | +#include <cerrno> | |
23 | +#include <chrono> | |
24 | +#include <cstdint> | |
25 | +#include <cstring> | |
26 | +#include <memory> | |
27 | +#include <mutex> | |
24 | 28 | |
25 | -#include <errno.h> | |
29 | +#include <base/base64.h> | |
30 | +#include <base/logging.h> | |
26 | 31 | |
32 | +#include "osi/include/leaky_bonded_queue.h" | |
27 | 33 | #include "osi/include/log.h" |
28 | 34 | #include "osi/include/osi.h" |
29 | -} | |
35 | +#include "stack/include/btm_api.h" | |
30 | 36 | |
31 | 37 | #include "osi/src/protos/bluetooth.pb.h" |
32 | 38 | |
33 | -#include <base/base64.h> | |
34 | -#include <google/protobuf/text_format.h> | |
35 | -#include <mutex> | |
39 | +#include "osi/include/metrics.h" | |
40 | +#include "osi/include/metrics_cpp.h" | |
41 | + | |
42 | +namespace system_bt_osi { | |
36 | 43 | |
37 | 44 | using clearcut::connectivity::A2DPSession; |
38 | 45 | using clearcut::connectivity::BluetoothLog; |
39 | 46 | using clearcut::connectivity::BluetoothSession; |
47 | +using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType; | |
48 | +using clearcut::connectivity::BluetoothSession_DisconnectReasonType; | |
40 | 49 | using clearcut::connectivity::DeviceInfo; |
41 | 50 | using clearcut::connectivity::DeviceInfo_DeviceType; |
42 | 51 | using clearcut::connectivity::PairEvent; |
@@ -46,156 +55,378 @@ using clearcut::connectivity::ScanEvent_ScanEventType; | ||
46 | 55 | using clearcut::connectivity::WakeEvent; |
47 | 56 | using clearcut::connectivity::WakeEvent_WakeEventType; |
48 | 57 | |
49 | -BluetoothLog *pending; | |
50 | -std::mutex log_lock; | |
58 | +uint64_t metrics_time_get_os_boottime_us(void) { | |
59 | + struct timespec ts_now; | |
60 | + clock_gettime(CLOCK_BOOTTIME, &ts_now); | |
51 | 61 | |
52 | -static void lazy_initialize(void) { | |
53 | - if (pending == nullptr) { | |
54 | - pending = BluetoothLog::default_instance().New(); | |
55 | - } | |
62 | + return ((uint64_t)ts_now.tv_sec * 1000000L) + | |
63 | + ((uint64_t)ts_now.tv_nsec / 1000); | |
56 | 64 | } |
57 | 65 | |
58 | -void metrics_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
59 | - uint32_t device_class, device_type_t device_type) { | |
60 | - std::lock_guard<std::mutex> lock(log_lock); | |
61 | - lazy_initialize(); | |
62 | - | |
63 | - PairEvent *event = pending->add_pair_event(); | |
64 | - | |
65 | - DeviceInfo *info = event->mutable_device_paired_with(); | |
66 | - | |
67 | - info->set_device_class(device_class); | |
68 | - | |
69 | - DeviceInfo_DeviceType type = DeviceInfo::DEVICE_TYPE_UNKNOWN; | |
70 | - | |
71 | - if (device_type == DEVICE_TYPE_BREDR) | |
72 | - type = DeviceInfo::DEVICE_TYPE_BREDR; | |
73 | - if (device_type == DEVICE_TYPE_LE) | |
74 | - type = DeviceInfo::DEVICE_TYPE_LE; | |
75 | - if (device_type == DEVICE_TYPE_DUMO) | |
76 | - type = DeviceInfo::DEVICE_TYPE_DUMO; | |
66 | +/* | |
67 | + * Get current OS boot time in millisecond | |
68 | + */ | |
69 | +static int64_t time_get_os_boottime_ms(void) { | |
70 | + return metrics_time_get_os_boottime_us() / 1000; | |
71 | +} | |
77 | 72 | |
78 | - info->set_device_type(type); | |
73 | +static float combine_averages(float avg_a, int64_t ct_a, float avg_b, | |
74 | + int64_t ct_b) { | |
75 | + if (ct_a > 0 && ct_b > 0) { | |
76 | + return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); | |
77 | + } else if (ct_b > 0) { | |
78 | + return avg_b; | |
79 | + } else { | |
80 | + return avg_a; | |
81 | + } | |
82 | +} | |
79 | 83 | |
80 | - event->set_disconnect_reason(disconnect_reason); | |
84 | +static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b, | |
85 | + int64_t ct_b) { | |
86 | + if (ct_a > 0 && ct_b > 0) { | |
87 | + return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); | |
88 | + } else if (ct_b > 0) { | |
89 | + return avg_b; | |
90 | + } else { | |
91 | + return avg_a; | |
92 | + } | |
93 | +} | |
81 | 94 | |
82 | - event->set_event_time_millis(timestamp_ms); | |
95 | +void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) { | |
96 | + if (metrics.audio_duration_ms >= 0) { | |
97 | + audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms); | |
98 | + audio_duration_ms += metrics.audio_duration_ms; | |
99 | + } | |
100 | + if (metrics.media_timer_min_ms >= 0) { | |
101 | + if (media_timer_min_ms < 0) { | |
102 | + media_timer_min_ms = metrics.media_timer_min_ms; | |
103 | + } else { | |
104 | + media_timer_min_ms = | |
105 | + std::min(media_timer_min_ms, metrics.media_timer_min_ms); | |
106 | + } | |
107 | + } | |
108 | + if (metrics.media_timer_max_ms >= 0) { | |
109 | + media_timer_max_ms = | |
110 | + std::max(media_timer_max_ms, metrics.media_timer_max_ms); | |
111 | + } | |
112 | + if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) { | |
113 | + if (media_timer_avg_ms < 0 || total_scheduling_count < 0) { | |
114 | + media_timer_avg_ms = metrics.media_timer_avg_ms; | |
115 | + total_scheduling_count = metrics.total_scheduling_count; | |
116 | + } else { | |
117 | + media_timer_avg_ms = combine_averages( | |
118 | + media_timer_avg_ms, total_scheduling_count, | |
119 | + metrics.media_timer_avg_ms, metrics.total_scheduling_count); | |
120 | + total_scheduling_count += metrics.total_scheduling_count; | |
121 | + } | |
122 | + } | |
123 | + if (metrics.buffer_overruns_max_count >= 0) { | |
124 | + buffer_overruns_max_count = | |
125 | + std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count); | |
126 | + } | |
127 | + if (metrics.buffer_overruns_total >= 0) { | |
128 | + buffer_overruns_total = | |
129 | + std::max(static_cast<int32_t>(0), buffer_overruns_total); | |
130 | + buffer_overruns_total += metrics.buffer_overruns_total; | |
131 | + } | |
132 | + if (metrics.buffer_underruns_average >= 0 && | |
133 | + metrics.buffer_underruns_count >= 0) { | |
134 | + if (buffer_underruns_average < 0 || buffer_underruns_count < 0) { | |
135 | + buffer_underruns_average = metrics.buffer_underruns_average; | |
136 | + buffer_underruns_count = metrics.buffer_underruns_count; | |
137 | + } else { | |
138 | + buffer_underruns_average = combine_averages( | |
139 | + buffer_underruns_average, buffer_underruns_count, | |
140 | + metrics.buffer_underruns_average, metrics.buffer_underruns_count); | |
141 | + buffer_underruns_count += metrics.buffer_underruns_count; | |
142 | + } | |
143 | + } | |
83 | 144 | } |
84 | 145 | |
85 | -void metrics_wake_event(wake_event_type_t type, const char *requestor, | |
86 | - const char *name, uint64_t timestamp_ms) { | |
87 | - std::lock_guard<std::mutex> lock(log_lock); | |
88 | - lazy_initialize(); | |
146 | +bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const { | |
147 | + return audio_duration_ms == rhs.audio_duration_ms && | |
148 | + media_timer_min_ms == rhs.media_timer_min_ms && | |
149 | + media_timer_max_ms == rhs.media_timer_max_ms && | |
150 | + media_timer_avg_ms == rhs.media_timer_avg_ms && | |
151 | + total_scheduling_count == rhs.total_scheduling_count && | |
152 | + buffer_overruns_max_count == rhs.buffer_overruns_max_count && | |
153 | + buffer_overruns_total == rhs.buffer_overruns_total && | |
154 | + buffer_underruns_average == rhs.buffer_underruns_average && | |
155 | + buffer_underruns_count == rhs.buffer_underruns_count; | |
156 | +} | |
89 | 157 | |
90 | - WakeEvent *event = pending->add_wake_event(); | |
158 | +static DeviceInfo_DeviceType get_device_type(device_type_t type) { | |
159 | + switch (type) { | |
160 | + case DEVICE_TYPE_BREDR: | |
161 | + return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR; | |
162 | + case DEVICE_TYPE_LE: | |
163 | + return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE; | |
164 | + case DEVICE_TYPE_DUMO: | |
165 | + return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO; | |
166 | + case DEVICE_TYPE_UNKNOWN: | |
167 | + default: | |
168 | + return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN; | |
169 | + } | |
170 | +} | |
91 | 171 | |
92 | - WakeEvent_WakeEventType waketype = WakeEvent::UNKNOWN; | |
172 | +static BluetoothSession_ConnectionTechnologyType get_connection_tech_type( | |
173 | + connection_tech_t type) { | |
174 | + switch (type) { | |
175 | + case CONNECTION_TECHNOLOGY_TYPE_LE: | |
176 | + return BluetoothSession_ConnectionTechnologyType:: | |
177 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE; | |
178 | + case CONNECTION_TECHNOLOGY_TYPE_BREDR: | |
179 | + return BluetoothSession_ConnectionTechnologyType:: | |
180 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR; | |
181 | + case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN: | |
182 | + default: | |
183 | + return BluetoothSession_ConnectionTechnologyType:: | |
184 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN; | |
185 | + } | |
186 | +} | |
93 | 187 | |
94 | - if (type == WAKE_EVENT_ACQUIRED) | |
95 | - waketype = WakeEvent::ACQUIRED; | |
96 | - if (type == WAKE_EVENT_RELEASED) | |
97 | - waketype = WakeEvent::RELEASED; | |
188 | +static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) { | |
189 | + switch (type) { | |
190 | + case SCAN_TECH_TYPE_LE: | |
191 | + return ScanEvent_ScanTechnologyType:: | |
192 | + ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE; | |
193 | + case SCAN_TECH_TYPE_BREDR: | |
194 | + return ScanEvent_ScanTechnologyType:: | |
195 | + ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR; | |
196 | + case SCAN_TECH_TYPE_BOTH: | |
197 | + return ScanEvent_ScanTechnologyType:: | |
198 | + ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH; | |
199 | + case SCAN_TYPE_UNKNOWN: | |
200 | + default: | |
201 | + return ScanEvent_ScanTechnologyType:: | |
202 | + ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN; | |
203 | + } | |
204 | +} | |
98 | 205 | |
99 | - event->set_wake_event_type(waketype); | |
206 | +static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) { | |
207 | + switch (type) { | |
208 | + case WAKE_EVENT_ACQUIRED: | |
209 | + return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED; | |
210 | + case WAKE_EVENT_RELEASED: | |
211 | + return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED; | |
212 | + case WAKE_EVENT_UNKNOWN: | |
213 | + default: | |
214 | + return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN; | |
215 | + } | |
216 | +} | |
100 | 217 | |
101 | - if (requestor) | |
102 | - event->set_requestor(requestor); | |
218 | +static BluetoothSession_DisconnectReasonType get_disconnect_reason_type( | |
219 | + disconnect_reason_t type) { | |
220 | + switch (type) { | |
221 | + case DISCONNECT_REASON_METRICS_DUMP: | |
222 | + return BluetoothSession_DisconnectReasonType:: | |
223 | + BluetoothSession_DisconnectReasonType_METRICS_DUMP; | |
224 | + case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS: | |
225 | + return BluetoothSession_DisconnectReasonType:: | |
226 | + BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS; | |
227 | + case DISCONNECT_REASON_UNKNOWN: | |
228 | + default: | |
229 | + return BluetoothSession_DisconnectReasonType:: | |
230 | + BluetoothSession_DisconnectReasonType_UNKNOWN; | |
231 | + } | |
232 | +} | |
103 | 233 | |
104 | - if (name) | |
105 | - event->set_name(name); | |
234 | +struct BluetoothMetricsLogger::impl { | |
235 | + impl(size_t max_bluetooth_session, size_t max_pair_event, | |
236 | + size_t max_wake_event, size_t max_scan_event) | |
237 | + : bt_session_queue_( | |
238 | + new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)), | |
239 | + pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)), | |
240 | + wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)), | |
241 | + scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) { | |
242 | + bluetooth_log_ = BluetoothLog::default_instance().New(); | |
243 | + bluetooth_session_ = nullptr; | |
244 | + bluetooth_session_start_time_ms_ = 0; | |
245 | + a2dp_session_metrics_ = A2dpSessionMetrics(); | |
246 | + } | |
106 | 247 | |
248 | + /* Bluetooth log lock protected */ | |
249 | + BluetoothLog* bluetooth_log_; | |
250 | + std::recursive_mutex bluetooth_log_lock_; | |
251 | + /* End Bluetooth log lock protected */ | |
252 | + /* Bluetooth session lock protected */ | |
253 | + BluetoothSession* bluetooth_session_; | |
254 | + uint64_t bluetooth_session_start_time_ms_; | |
255 | + A2dpSessionMetrics a2dp_session_metrics_; | |
256 | + std::recursive_mutex bluetooth_session_lock_; | |
257 | + /* End bluetooth session lock protected */ | |
258 | + std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_; | |
259 | + std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_; | |
260 | + std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_; | |
261 | + std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_; | |
262 | +}; | |
263 | + | |
264 | +BluetoothMetricsLogger::BluetoothMetricsLogger() | |
265 | + : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent, | |
266 | + kMaxNumWakeEvent, kMaxNumScanEvent)) {} | |
267 | + | |
268 | +void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason, | |
269 | + uint64_t timestamp_ms, | |
270 | + uint32_t device_class, | |
271 | + device_type_t device_type) { | |
272 | + PairEvent* event = new PairEvent(); | |
273 | + DeviceInfo* info = event->mutable_device_paired_with(); | |
274 | + info->set_device_class(device_class); | |
275 | + info->set_device_type(get_device_type(device_type)); | |
276 | + event->set_disconnect_reason(disconnect_reason); | |
107 | 277 | event->set_event_time_millis(timestamp_ms); |
278 | + pimpl_->pair_event_queue_->Enqueue(event); | |
279 | + { | |
280 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); | |
281 | + pimpl_->bluetooth_log_->set_num_pair_event( | |
282 | + pimpl_->bluetooth_log_->num_pair_event() + 1); | |
283 | + } | |
108 | 284 | } |
109 | 285 | |
110 | -void metrics_scan_event(bool start, const char *initator, scan_tech_t type, | |
111 | - uint32_t results, uint64_t timestamp_ms) { | |
112 | - std::lock_guard<std::mutex> lock(log_lock); | |
113 | - lazy_initialize(); | |
114 | - | |
115 | - ScanEvent *event = pending->add_scan_event(); | |
286 | +void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type, | |
287 | + const std::string& requestor, | |
288 | + const std::string& name, | |
289 | + uint64_t timestamp_ms) { | |
290 | + WakeEvent* event = new WakeEvent(); | |
291 | + event->set_wake_event_type(get_wake_event_type(type)); | |
292 | + event->set_requestor(requestor); | |
293 | + event->set_name(name); | |
294 | + event->set_event_time_millis(timestamp_ms); | |
295 | + pimpl_->wake_event_queue_->Enqueue(event); | |
296 | + { | |
297 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); | |
298 | + pimpl_->bluetooth_log_->set_num_wake_event( | |
299 | + pimpl_->bluetooth_log_->num_wake_event() + 1); | |
300 | + } | |
301 | +} | |
116 | 302 | |
117 | - if (start) | |
303 | +void BluetoothMetricsLogger::LogScanEvent(bool start, | |
304 | + const std::string& initator, | |
305 | + scan_tech_t type, uint32_t results, | |
306 | + uint64_t timestamp_ms) { | |
307 | + ScanEvent* event = new ScanEvent(); | |
308 | + if (start) { | |
118 | 309 | event->set_scan_event_type(ScanEvent::SCAN_EVENT_START); |
119 | - else | |
310 | + } else { | |
120 | 311 | event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP); |
121 | - | |
122 | - if (initator) | |
123 | - event->set_initiator(initator); | |
124 | - | |
125 | - ScanEvent::ScanTechnologyType scantype = ScanEvent::SCAN_TYPE_UNKNOWN; | |
126 | - | |
127 | - if (type == SCAN_TECH_TYPE_LE) | |
128 | - scantype = ScanEvent::SCAN_TECH_TYPE_LE; | |
129 | - if (type == SCAN_TECH_TYPE_BREDR) | |
130 | - scantype = ScanEvent::SCAN_TECH_TYPE_BREDR; | |
131 | - if (type == SCAN_TECH_TYPE_BOTH) | |
132 | - scantype = ScanEvent::SCAN_TECH_TYPE_BOTH; | |
133 | - | |
134 | - event->set_scan_technology_type(scantype); | |
135 | - | |
312 | + } | |
313 | + event->set_initiator(initator); | |
314 | + event->set_scan_technology_type(get_scan_tech_type(type)); | |
136 | 315 | event->set_number_results(results); |
137 | - | |
138 | 316 | event->set_event_time_millis(timestamp_ms); |
317 | + pimpl_->scan_event_queue_->Enqueue(event); | |
318 | + { | |
319 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); | |
320 | + pimpl_->bluetooth_log_->set_num_scan_event( | |
321 | + pimpl_->bluetooth_log_->num_scan_event() + 1); | |
322 | + } | |
323 | +} | |
324 | + | |
325 | +void BluetoothMetricsLogger::LogBluetoothSessionStart( | |
326 | + connection_tech_t connection_tech_type, uint64_t timestamp_ms) { | |
327 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); | |
328 | + if (pimpl_->bluetooth_session_ != nullptr) { | |
329 | + LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS, | |
330 | + 0); | |
331 | + } | |
332 | + if (timestamp_ms == 0) { | |
333 | + timestamp_ms = time_get_os_boottime_ms(); | |
334 | + } | |
335 | + pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms; | |
336 | + pimpl_->bluetooth_session_ = new BluetoothSession(); | |
337 | + pimpl_->bluetooth_session_->set_connection_technology_type( | |
338 | + get_connection_tech_type(connection_tech_type)); | |
339 | +} | |
340 | + | |
341 | +void BluetoothMetricsLogger::LogBluetoothSessionEnd( | |
342 | + disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) { | |
343 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); | |
344 | + if (pimpl_->bluetooth_session_ == nullptr) { | |
345 | + return; | |
346 | + } | |
347 | + if (timestamp_ms == 0) { | |
348 | + timestamp_ms = time_get_os_boottime_ms(); | |
349 | + } | |
350 | + int64_t session_duration_sec = | |
351 | + (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000; | |
352 | + pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec); | |
353 | + pimpl_->bluetooth_session_->set_disconnect_reason_type( | |
354 | + get_disconnect_reason_type(disconnect_reason)); | |
355 | + pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_); | |
356 | + pimpl_->bluetooth_session_ = nullptr; | |
357 | + { | |
358 | + std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_); | |
359 | + pimpl_->bluetooth_log_->set_num_bluetooth_session( | |
360 | + pimpl_->bluetooth_log_->num_bluetooth_session() + 1); | |
361 | + } | |
139 | 362 | } |
140 | 363 | |
141 | -void metrics_a2dp_session(int64_t session_duration_sec, | |
142 | - const char *disconnect_reason, | |
143 | - uint32_t device_class, | |
144 | - int32_t media_timer_min_ms, | |
145 | - int32_t media_timer_max_ms, | |
146 | - int32_t media_timer_avg_ms, | |
147 | - int32_t buffer_overruns_max_count, | |
148 | - int32_t buffer_overruns_total, | |
149 | - float buffer_underruns_average, | |
150 | - int32_t buffer_underruns_count) { | |
151 | - std::lock_guard<std::mutex> lock(log_lock); | |
152 | - lazy_initialize(); | |
153 | - | |
154 | - BluetoothSession *bt_session = pending->add_session(); | |
155 | - | |
156 | - // Set connection type: for A2DP it is always BR/EDR | |
157 | - BluetoothSession::ConnectionTechnologyType conn_type = | |
158 | - BluetoothSession::CONNECTION_TECHNOLOGY_TYPE_BREDR; | |
159 | - bt_session->set_connection_technology_type(conn_type); | |
160 | - | |
161 | - bt_session->set_session_duration_sec(session_duration_sec); | |
162 | - if (disconnect_reason != NULL) | |
163 | - bt_session->set_disconnect_reason(disconnect_reason); | |
164 | - | |
165 | - // Set device: class and type are pre-defined | |
166 | - DeviceInfo *info = bt_session->mutable_device_connected_to(); | |
364 | +void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo( | |
365 | + uint32_t device_class, device_type_t device_type) { | |
366 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); | |
367 | + if (pimpl_->bluetooth_session_ == nullptr) { | |
368 | + LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0); | |
369 | + } | |
370 | + DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to(); | |
167 | 371 | info->set_device_class(device_class); |
168 | 372 | info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR); |
373 | +} | |
169 | 374 | |
170 | - A2DPSession *a2dp_session = bt_session->mutable_a2dp_session(); | |
171 | - a2dp_session->set_media_timer_min_millis(media_timer_min_ms); | |
172 | - a2dp_session->set_media_timer_max_millis(media_timer_max_ms); | |
173 | - a2dp_session->set_media_timer_avg_millis(media_timer_avg_ms); | |
174 | - a2dp_session->set_buffer_overruns_max_count(buffer_overruns_max_count); | |
175 | - a2dp_session->set_buffer_overruns_total(buffer_overruns_total); | |
176 | - a2dp_session->set_buffer_underruns_average(buffer_underruns_average); | |
177 | - a2dp_session->set_buffer_underruns_count(buffer_underruns_count); | |
375 | +void BluetoothMetricsLogger::LogA2dpSession( | |
376 | + const A2dpSessionMetrics& a2dp_session_metrics) { | |
377 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); | |
378 | + if (pimpl_->bluetooth_session_ == nullptr) { | |
379 | + // When no bluetooth session exist, create one on system's behalf | |
380 | + // Set connection type: for A2DP it is always BR/EDR | |
381 | + LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); | |
382 | + LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR); | |
383 | + } | |
384 | + // Accumulate metrics | |
385 | + pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics); | |
386 | + // Get or allocate new A2DP session object | |
387 | + A2DPSession* a2dp_session = | |
388 | + pimpl_->bluetooth_session_->mutable_a2dp_session(); | |
389 | + a2dp_session->set_audio_duration_millis( | |
390 | + pimpl_->a2dp_session_metrics_.audio_duration_ms); | |
391 | + a2dp_session->set_media_timer_min_millis( | |
392 | + pimpl_->a2dp_session_metrics_.media_timer_min_ms); | |
393 | + a2dp_session->set_media_timer_max_millis( | |
394 | + pimpl_->a2dp_session_metrics_.media_timer_max_ms); | |
395 | + a2dp_session->set_media_timer_avg_millis( | |
396 | + pimpl_->a2dp_session_metrics_.media_timer_avg_ms); | |
397 | + a2dp_session->set_buffer_overruns_max_count( | |
398 | + pimpl_->a2dp_session_metrics_.buffer_overruns_max_count); | |
399 | + a2dp_session->set_buffer_overruns_total( | |
400 | + pimpl_->a2dp_session_metrics_.buffer_overruns_total); | |
401 | + a2dp_session->set_buffer_underruns_average( | |
402 | + pimpl_->a2dp_session_metrics_.buffer_underruns_average); | |
403 | + a2dp_session->set_buffer_underruns_count( | |
404 | + pimpl_->a2dp_session_metrics_.buffer_underruns_count); | |
178 | 405 | } |
179 | 406 | |
180 | -void metrics_write(int fd, bool clear) { | |
181 | - log_lock.lock(); | |
407 | +void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) { | |
408 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); | |
409 | + LOG_DEBUG(LOG_TAG, "%s building metrics", __func__); | |
410 | + Build(); | |
182 | 411 | LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__); |
183 | - lazy_initialize(); | |
184 | - | |
185 | - std::string serialized; | |
186 | - if (!pending->SerializeToString(&serialized)) { | |
412 | + if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) { | |
187 | 413 | LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__); |
188 | 414 | return; |
189 | 415 | } |
190 | - | |
191 | 416 | if (clear) { |
192 | - pending->Clear(); | |
417 | + pimpl_->bluetooth_log_->Clear(); | |
193 | 418 | } |
194 | - log_lock.unlock(); | |
419 | +} | |
195 | 420 | |
196 | - std::string protoBase64; | |
197 | - base::Base64Encode(serialized, &protoBase64); | |
421 | +void BluetoothMetricsLogger::WriteBase64String(std::string* serialized, | |
422 | + bool clear) { | |
423 | + this->WriteString(serialized, clear); | |
424 | + base::Base64Encode(*serialized, serialized); | |
425 | +} | |
198 | 426 | |
427 | +void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) { | |
428 | + std::string protoBase64; | |
429 | + this->WriteBase64String(&protoBase64, clear); | |
199 | 430 | ssize_t ret; |
200 | 431 | OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size())); |
201 | 432 | if (ret == -1) { |
@@ -204,23 +435,137 @@ void metrics_write(int fd, bool clear) { | ||
204 | 435 | } |
205 | 436 | } |
206 | 437 | |
207 | -void metrics_print(int fd, bool clear) { | |
208 | - log_lock.lock(); | |
209 | - LOG_DEBUG(LOG_TAG, "%s printing metrics", __func__); | |
210 | - lazy_initialize(); | |
211 | - | |
212 | - std::string pretty_output; | |
213 | - google::protobuf::TextFormat::PrintToString(*pending, &pretty_output); | |
438 | +void BluetoothMetricsLogger::CutoffSession() { | |
439 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); | |
440 | + if (pimpl_->bluetooth_session_ != nullptr) { | |
441 | + BluetoothSession* new_bt_session = | |
442 | + new BluetoothSession(*pimpl_->bluetooth_session_); | |
443 | + new_bt_session->clear_a2dp_session(); | |
444 | + new_bt_session->clear_rfcomm_session(); | |
445 | + LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0); | |
446 | + pimpl_->bluetooth_session_ = new_bt_session; | |
447 | + pimpl_->bluetooth_session_start_time_ms_ = time_get_os_boottime_ms(); | |
448 | + pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); | |
449 | + } | |
450 | +} | |
214 | 451 | |
215 | - if (clear) { | |
216 | - pending->Clear(); | |
452 | +void BluetoothMetricsLogger::Build() { | |
453 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); | |
454 | + CutoffSession(); | |
455 | + BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_; | |
456 | + while (!pimpl_->bt_session_queue_->Empty() && | |
457 | + static_cast<size_t>(bluetooth_log->session_size()) <= | |
458 | + pimpl_->bt_session_queue_->Capacity()) { | |
459 | + bluetooth_log->mutable_session()->AddAllocated( | |
460 | + pimpl_->bt_session_queue_->Dequeue()); | |
461 | + } | |
462 | + while (!pimpl_->pair_event_queue_->Empty() && | |
463 | + static_cast<size_t>(bluetooth_log->pair_event_size()) <= | |
464 | + pimpl_->pair_event_queue_->Capacity()) { | |
465 | + bluetooth_log->mutable_pair_event()->AddAllocated( | |
466 | + pimpl_->pair_event_queue_->Dequeue()); | |
467 | + } | |
468 | + while (!pimpl_->scan_event_queue_->Empty() && | |
469 | + static_cast<size_t>(bluetooth_log->scan_event_size()) <= | |
470 | + pimpl_->scan_event_queue_->Capacity()) { | |
471 | + bluetooth_log->mutable_scan_event()->AddAllocated( | |
472 | + pimpl_->scan_event_queue_->Dequeue()); | |
473 | + } | |
474 | + while (!pimpl_->wake_event_queue_->Empty() && | |
475 | + static_cast<size_t>(bluetooth_log->wake_event_size()) <= | |
476 | + pimpl_->wake_event_queue_->Capacity()) { | |
477 | + bluetooth_log->mutable_wake_event()->AddAllocated( | |
478 | + pimpl_->wake_event_queue_->Dequeue()); | |
217 | 479 | } |
218 | - log_lock.unlock(); | |
480 | + while (!pimpl_->bt_session_queue_->Empty() && | |
481 | + static_cast<size_t>(bluetooth_log->wake_event_size()) <= | |
482 | + pimpl_->wake_event_queue_->Capacity()) { | |
483 | + bluetooth_log->mutable_wake_event()->AddAllocated( | |
484 | + pimpl_->wake_event_queue_->Dequeue()); | |
485 | + } | |
486 | +} | |
219 | 487 | |
220 | - ssize_t ret; | |
221 | - OSI_NO_INTR(ret = write(fd, pretty_output.c_str(), pretty_output.size())); | |
222 | - if (ret == -1) { | |
223 | - LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__, | |
224 | - strerror(errno), errno); | |
488 | +void BluetoothMetricsLogger::ResetSession() { | |
489 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); | |
490 | + if (pimpl_->bluetooth_session_ != nullptr) { | |
491 | + delete pimpl_->bluetooth_session_; | |
492 | + pimpl_->bluetooth_session_ = nullptr; | |
225 | 493 | } |
494 | + pimpl_->bluetooth_session_start_time_ms_ = 0; | |
495 | + pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); | |
496 | +} | |
497 | + | |
498 | +void BluetoothMetricsLogger::ResetLog() { | |
499 | + std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); | |
500 | + pimpl_->bluetooth_log_->Clear(); | |
501 | +} | |
502 | + | |
503 | +void BluetoothMetricsLogger::Reset() { | |
504 | + ResetSession(); | |
505 | + ResetLog(); | |
506 | + pimpl_->bt_session_queue_->Clear(); | |
507 | + pimpl_->pair_event_queue_->Clear(); | |
508 | + pimpl_->wake_event_queue_->Clear(); | |
509 | + pimpl_->scan_event_queue_->Clear(); | |
510 | +} | |
511 | + | |
512 | +} // namespace system_bt_osi | |
513 | + | |
514 | +using system_bt_osi::BluetoothMetricsLogger; | |
515 | + | |
516 | +void metrics_log_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
517 | + uint32_t device_class, device_type_t device_type) { | |
518 | + BluetoothMetricsLogger::GetInstance()->LogPairEvent(disconnect_reason, | |
519 | + timestamp_ms, device_class, device_type); | |
520 | +} | |
521 | + | |
522 | +void metrics_log_wake_event(wake_event_type_t type, const char* requestor, | |
523 | + const char* name, uint64_t timestamp_ms) { | |
524 | + std::string requestor_str(requestor); | |
525 | + std::string name_str(name); | |
526 | + BluetoothMetricsLogger::GetInstance()->LogWakeEvent(type, requestor_str, | |
527 | + name_str, timestamp_ms); | |
528 | +} | |
529 | + | |
530 | +void metrics_log_scan_event(bool start, const char* initator, scan_tech_t type, | |
531 | + uint32_t results, uint64_t timestamp_ms) { | |
532 | + std::string initator_str(initator); | |
533 | + BluetoothMetricsLogger::GetInstance()->LogScanEvent(start, initator_str, type, | |
534 | + results, timestamp_ms); | |
535 | +} | |
536 | + | |
537 | +void metrics_log_bluetooth_session_start(connection_tech_t connection_tech_type, | |
538 | + uint64_t timestamp_ms) { | |
539 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
540 | + connection_tech_type, 0); | |
541 | +} | |
542 | + | |
543 | +void metrics_log_bluetooth_session_end(disconnect_reason_t disconnect_reason, | |
544 | + uint64_t timestamp_ms) { | |
545 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( | |
546 | + disconnect_reason, timestamp_ms); | |
547 | +} | |
548 | + | |
549 | +void metrics_log_bluetooth_session_device_info(uint32_t device_class, | |
550 | + device_type_t device_type) { | |
551 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( | |
552 | + device_class, device_type); | |
553 | +} | |
554 | + | |
555 | +void metrics_log_a2dp_session(A2dpSessionMetrics_t* metrics) { | |
556 | + system_bt_osi::A2dpSessionMetrics metrics_obj; | |
557 | + metrics_obj.audio_duration_ms = metrics->audio_duration_ms; | |
558 | + metrics_obj.media_timer_min_ms = metrics->media_timer_min_ms; | |
559 | + metrics_obj.media_timer_max_ms = metrics->media_timer_max_ms; | |
560 | + metrics_obj.media_timer_avg_ms = metrics->media_timer_avg_ms; | |
561 | + metrics_obj.total_scheduling_count = metrics->total_scheduling_count; | |
562 | + metrics_obj.buffer_overruns_max_count = metrics->buffer_overruns_max_count; | |
563 | + metrics_obj.buffer_overruns_total = metrics->buffer_overruns_total; | |
564 | + metrics_obj.buffer_underruns_average = metrics->buffer_underruns_average; | |
565 | + metrics_obj.buffer_underruns_count = metrics->buffer_underruns_count; | |
566 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics_obj); | |
567 | +} | |
568 | + | |
569 | +void metrics_write_base64(int fd, bool clear) { | |
570 | + BluetoothMetricsLogger::GetInstance()->WriteBase64(fd, clear); | |
226 | 571 | } |
@@ -15,46 +15,230 @@ | ||
15 | 15 | * limitations under the License. |
16 | 16 | * |
17 | 17 | ******************************************************************************/ |
18 | +#define LOG_TAG "bt_osi_metrics" | |
18 | 19 | |
20 | +#include <unistd.h> | |
21 | +#include <algorithm> | |
22 | +#include <cerrno> | |
23 | +#include <chrono> | |
24 | +#include <cstdint> | |
25 | +#include <cstring> | |
26 | +#include <memory> | |
27 | +#include <mutex> | |
19 | 28 | |
20 | -#define LOG_TAG "bt_osi_metrics" | |
29 | +#include <base/base64.h> | |
30 | +#include <base/logging.h> | |
31 | + | |
32 | +#include "osi/include/leaky_bonded_queue.h" | |
33 | +#include "osi/include/log.h" | |
34 | +#include "osi/include/osi.h" | |
35 | +#include "osi/include/time.h" | |
21 | 36 | |
22 | -extern "C" { | |
23 | 37 | #include "osi/include/metrics.h" |
38 | +#include "osi/include/metrics_cpp.h" | |
39 | + | |
40 | + | |
41 | +namespace system_bt_osi { | |
42 | + | |
43 | +// Maximum number of log entries for each repeated field | |
44 | +#define MAX_NUM_BLUETOOTH_SESSION 50 | |
45 | +#define MAX_NUM_PAIR_EVENT 50 | |
46 | +#define MAX_NUM_WAKE_EVENT 50 | |
47 | +#define MAX_NUM_SCAN_EVENT 50 | |
48 | + | |
49 | +static float combine_averages(float avg_a, int64_t ct_a, float avg_b, | |
50 | + int64_t ct_b) { | |
51 | + if (ct_a > 0 && ct_b > 0) { | |
52 | + return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); | |
53 | + } else if (ct_b > 0) { | |
54 | + return avg_b; | |
55 | + } else { | |
56 | + return avg_a; | |
57 | + } | |
58 | +} | |
59 | + | |
60 | +static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b, | |
61 | + int64_t ct_b) { | |
62 | + if (ct_a > 0 && ct_b > 0) { | |
63 | + return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); | |
64 | + } else if (ct_b > 0) { | |
65 | + return avg_b; | |
66 | + } else { | |
67 | + return avg_a; | |
68 | + } | |
69 | +} | |
70 | + | |
71 | +void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) { | |
72 | + if (metrics.audio_duration_ms > 0) { | |
73 | + audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms); | |
74 | + audio_duration_ms += metrics.audio_duration_ms; | |
75 | + } | |
76 | + if (metrics.media_timer_min_ms > 0) { | |
77 | + if (media_timer_min_ms < 0) { | |
78 | + media_timer_min_ms = metrics.media_timer_min_ms; | |
79 | + } else { | |
80 | + media_timer_min_ms = | |
81 | + std::min(media_timer_min_ms, metrics.media_timer_min_ms); | |
82 | + } | |
83 | + } | |
84 | + if (metrics.media_timer_max_ms > 0) { | |
85 | + media_timer_max_ms = | |
86 | + std::max(media_timer_max_ms, metrics.media_timer_max_ms); | |
87 | + } | |
88 | + if (metrics.media_timer_avg_ms > 0 && metrics.total_scheduling_count > 0) { | |
89 | + if (media_timer_avg_ms < 0 || total_scheduling_count < 0) { | |
90 | + media_timer_avg_ms = metrics.media_timer_avg_ms; | |
91 | + total_scheduling_count = metrics.total_scheduling_count; | |
92 | + } else { | |
93 | + media_timer_avg_ms = combine_averages( | |
94 | + media_timer_avg_ms, total_scheduling_count, | |
95 | + metrics.media_timer_avg_ms, metrics.total_scheduling_count); | |
96 | + total_scheduling_count += metrics.total_scheduling_count; | |
97 | + } | |
98 | + } | |
99 | + if (metrics.buffer_overruns_max_count > 0) { | |
100 | + buffer_overruns_max_count = | |
101 | + std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count); | |
102 | + } | |
103 | + if (metrics.buffer_overruns_total > 0) { | |
104 | + buffer_overruns_total = | |
105 | + std::max(static_cast<int32_t>(0), buffer_overruns_total); | |
106 | + buffer_overruns_total += metrics.buffer_overruns_total; | |
107 | + } | |
108 | + if (metrics.buffer_underruns_average > 0 && | |
109 | + metrics.buffer_underruns_count > 0) { | |
110 | + if (buffer_underruns_average < 0 || buffer_underruns_count < 0) { | |
111 | + buffer_underruns_average = metrics.buffer_underruns_average; | |
112 | + buffer_underruns_count = metrics.buffer_underruns_count; | |
113 | + } else { | |
114 | + buffer_underruns_average = combine_averages( | |
115 | + metrics.buffer_underruns_average, metrics.buffer_underruns_count, | |
116 | + buffer_underruns_average, buffer_underruns_count); | |
117 | + buffer_underruns_count += metrics.buffer_underruns_count; | |
118 | + } | |
119 | + } | |
120 | +} | |
121 | + | |
122 | +bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const { | |
123 | + return audio_duration_ms == rhs.audio_duration_ms && | |
124 | + media_timer_min_ms == rhs.media_timer_min_ms && | |
125 | + media_timer_max_ms == rhs.media_timer_max_ms && | |
126 | + media_timer_avg_ms == rhs.media_timer_avg_ms && | |
127 | + total_scheduling_count == rhs.total_scheduling_count && | |
128 | + buffer_overruns_max_count == rhs.buffer_overruns_max_count && | |
129 | + buffer_overruns_total == rhs.buffer_overruns_total && | |
130 | + buffer_underruns_average == rhs.buffer_underruns_average && | |
131 | + buffer_underruns_count == rhs.buffer_underruns_count; | |
132 | +} | |
133 | + | |
134 | +struct BluetoothMetricsLogger::impl { | |
135 | + // TODO(siyuanh): Implement for linux | |
136 | +}; | |
137 | + | |
138 | +BluetoothMetricsLogger::BluetoothMetricsLogger() : pimpl_(new impl) {} | |
139 | + | |
140 | +void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason, | |
141 | + uint64_t timestamp_ms, | |
142 | + uint32_t device_class, | |
143 | + device_type_t device_type) { | |
144 | + // TODO(siyuanh): Implement for linux | |
145 | +} | |
146 | + | |
147 | +void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type, | |
148 | + const std::string& requestor, | |
149 | + const std::string& name, | |
150 | + uint64_t timestamp_ms) { | |
151 | + // TODO(siyuanh): Implement for linux | |
152 | +} | |
153 | + | |
154 | +void BluetoothMetricsLogger::LogScanEvent(bool start, | |
155 | + const std::string& initator, | |
156 | + scan_tech_t type, uint32_t results, | |
157 | + uint64_t timestamp_ms) { | |
158 | + // TODO(siyuanh): Implement for linux | |
159 | +} | |
160 | + | |
161 | +void BluetoothMetricsLogger::LogBluetoothSessionStart( | |
162 | + connection_tech_t connection_tech_type, uint64_t timestamp_ms) { | |
163 | + // TODO(siyuanh): Implement for linux | |
164 | +} | |
165 | + | |
166 | +void BluetoothMetricsLogger::LogBluetoothSessionEnd( | |
167 | + const std::string& disconnect_reason, uint64_t timestamp_ms) { | |
168 | + // TODO(siyuanh): Implement for linux | |
169 | +} | |
170 | + | |
171 | +void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo( | |
172 | + uint32_t device_class, device_type_t device_type) { | |
173 | + // TODO(siyuanh): Implement for linux | |
174 | +} | |
175 | + | |
176 | +void BluetoothMetricsLogger::LogA2dpSession( | |
177 | + const A2dpSessionMetrics& a2dp_session_metrics) { | |
178 | + // TODO(siyuanh): Implement for linux | |
179 | +} | |
180 | + | |
181 | +void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) { | |
182 | + // TODO(siyuanh): Implement for linux | |
183 | +} | |
184 | + | |
185 | +void BluetoothMetricsLogger::WriteBase64String(std::string* serialized, | |
186 | + bool clear) { | |
187 | + // TODO(siyuanh): Implement for linux | |
188 | +} | |
189 | + | |
190 | +void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) { | |
191 | + // TODO(siyuanh): Implement for linux | |
192 | +} | |
193 | + | |
194 | +void BluetoothMetricsLogger::CutoffSession() { | |
195 | + // TODO(siyuanh): Implement for linux | |
196 | +} | |
197 | + | |
198 | +void BluetoothMetricsLogger::Build() { | |
199 | + // TODO(siyuanh): Implement for linux | |
200 | +} | |
201 | + | |
202 | +void BluetoothMetricsLogger::Reset() { | |
203 | + // TODO(siyuanh): Implement for linux | |
204 | +} | |
205 | + | |
206 | +} // namespace system_bt_osi | |
207 | + | |
208 | +void metrics_log_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
209 | + uint32_t device_class, device_type_t device_type) { | |
210 | + // TODO(siyuanh): Implement for linux | |
211 | +} | |
212 | + | |
213 | +void metrics_log_wake_event(wake_event_type_t type, const char* requestor, | |
214 | + const char* name, uint64_t timestamp_ms) { | |
215 | + // TODO(siyuanh): Implement for linux | |
24 | 216 | } |
25 | 217 | |
26 | -void metrics_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms, | |
27 | - uint32_t device_class, device_type_t device_type) { | |
28 | - //TODO(jpawlowski): implement | |
218 | +void metrics_log_scan_event(bool start, const char* initator, scan_tech_t type, | |
219 | + uint32_t results, uint64_t timestamp_ms) { | |
220 | + // TODO(siyuanh): Implement for linux | |
29 | 221 | } |
30 | 222 | |
31 | -void metrics_wake_event(wake_event_type_t type, const char *requestor, | |
32 | - const char *name, uint64_t timestamp_ms) { | |
33 | - //TODO(jpawlowski): implement | |
223 | +void metrics_log_bluetooth_session_start(connection_tech_t connection_tech_type, | |
224 | + uint64_t timestamp_ms) { | |
225 | + // TODO(siyuanh): Implement for linux | |
34 | 226 | } |
35 | 227 | |
36 | -void metrics_scan_event(bool start, const char *initator, scan_tech_t type, | |
37 | - uint32_t results, uint64_t timestamp_ms) { | |
38 | - //TODO(jpawlowski): implement | |
228 | +void metrics_log_bluetooth_session_end(const char* disconnect_reason, | |
229 | + uint64_t timestamp_ms) { | |
230 | + // TODO(siyuanh): Implement for linux | |
39 | 231 | } |
40 | 232 | |
41 | -void metrics_a2dp_session(int64_t session_duration_sec, | |
42 | - const char *disconnect_reason, | |
43 | - uint32_t device_class, | |
44 | - int32_t media_timer_min_ms, | |
45 | - int32_t media_timer_max_ms, | |
46 | - int32_t media_timer_avg_ms, | |
47 | - int32_t buffer_overruns_max_count, | |
48 | - int32_t buffer_overruns_total, | |
49 | - float buffer_underruns_average, | |
50 | - int32_t buffer_underruns_count) { | |
51 | - //TODO(jpawlowski): implement | |
233 | +void metrics_log_bluetooth_session_device_info(uint32_t device_class, | |
234 | + device_type_t device_type) { | |
235 | + // TODO(siyuanh): Implement for linux | |
52 | 236 | } |
53 | 237 | |
54 | -void metrics_write(int fd, bool clear) { | |
55 | - //TODO(jpawlowski): implement | |
238 | +void metrics_log_a2dp_session(A2dpSessionMetrics_t* metrics) { | |
239 | + // TODO(siyuanh): Implement for linux | |
56 | 240 | } |
57 | 241 | |
58 | -void metrics_print(int fd, bool clear) { | |
59 | - //TODO(jpawlowski): implement | |
242 | +void metrics_write_base64(int fd, bool clear) { | |
243 | + // TODO(siyuanh): Implement for linux | |
60 | 244 | } |
@@ -24,6 +24,21 @@ message BluetoothLog { | ||
24 | 24 | |
25 | 25 | // Scan event information. |
26 | 26 | repeated ScanEvent scan_event = 4; |
27 | + | |
28 | + // Number of bonded devices. | |
29 | + optional int32 num_bonded_devices = 5; | |
30 | + | |
31 | + // Number of BluetoothSession including discarded ones beyond capacity | |
32 | + optional int64 num_bluetooth_session = 6; | |
33 | + | |
34 | + // Number of PairEvent including discarded ones beyond capacity | |
35 | + optional int64 num_pair_event = 7; | |
36 | + | |
37 | + // Number of WakeEvent including discarded ones beyond capacity | |
38 | + optional int64 num_wake_event = 8; | |
39 | + | |
40 | + // Number of ScanEvent including discarded ones beyond capacity | |
41 | + optional int64 num_scan_event = 9; | |
27 | 42 | } |
28 | 43 | |
29 | 44 | // The information about the device. |
@@ -63,6 +78,17 @@ message BluetoothSession { | ||
63 | 78 | CONNECTION_TECHNOLOGY_TYPE_BREDR = 2; |
64 | 79 | } |
65 | 80 | |
81 | + enum DisconnectReasonType { | |
82 | + UNKNOWN = 0; | |
83 | + | |
84 | + // A metrics dump takes a snapshot of current Bluetooth session and thus | |
85 | + // is not a real disconnect, but a discontinuation in metrics logging. | |
86 | + // This enum indicates this situation. | |
87 | + METRICS_DUMP = 1; | |
88 | + | |
89 | + NEXT_START_WITHOUT_END_PREVIOUS = 2; | |
90 | + } | |
91 | + | |
66 | 92 | // Duration of the session. |
67 | 93 | optional int64 session_duration_sec = 2; |
68 | 94 |
@@ -70,7 +96,7 @@ message BluetoothSession { | ||
70 | 96 | optional ConnectionTechnologyType connection_technology_type = 3; |
71 | 97 | |
72 | 98 | // Reason for disconnecting. |
73 | - optional string disconnect_reason = 4; | |
99 | + optional string disconnect_reason = 4 [deprecated=true]; | |
74 | 100 | |
75 | 101 | // The information about the device which it is connected to. |
76 | 102 | optional DeviceInfo device_connected_to = 5; |
@@ -78,8 +104,11 @@ message BluetoothSession { | ||
78 | 104 | // The information about the RFComm session. |
79 | 105 | optional RFCommSession rfcomm_session = 6; |
80 | 106 | |
81 | - // The information about the A2DP session. | |
107 | + // The information about the A2DP audio session. | |
82 | 108 | optional A2DPSession a2dp_session = 7; |
109 | + | |
110 | + // Numeric reason for disconnecting as defined in metrics.h | |
111 | + optional DisconnectReasonType disconnect_reason_type = 8; | |
83 | 112 | } |
84 | 113 | |
85 | 114 | message RFCommSession { |
@@ -91,7 +120,7 @@ message RFCommSession { | ||
91 | 120 | optional int32 tx_bytes = 2; |
92 | 121 | } |
93 | 122 | |
94 | -// Session information that gets logged for every A2DP session. | |
123 | +// Session information that gets logged for A2DP session. | |
95 | 124 | message A2DPSession { |
96 | 125 | |
97 | 126 | // Media timer in milliseconds. |
@@ -114,6 +143,9 @@ message A2DPSession { | ||
114 | 143 | |
115 | 144 | // Buffer underruns count. |
116 | 145 | optional int32 buffer_underruns_count = 7; |
146 | + | |
147 | + // Total audio time in this A2DP session | |
148 | + optional int64 audio_duration_millis = 8; | |
117 | 149 | } |
118 | 150 | |
119 | 151 | message PairEvent { |
@@ -294,7 +294,7 @@ static void update_wakelock_acquired_stats(bt_status_t acquired_status) { | ||
294 | 294 | |
295 | 295 | pthread_mutex_unlock(&monitor); |
296 | 296 | |
297 | - metrics_wake_event(WAKE_EVENT_ACQUIRED, NULL, WAKE_LOCK_ID, now_ms); | |
297 | + metrics_log_wake_event(WAKE_EVENT_ACQUIRED, "", "", now_ms); | |
298 | 298 | } |
299 | 299 | |
300 | 300 | // |
@@ -338,7 +338,7 @@ static void update_wakelock_released_stats(bt_status_t released_status) { | ||
338 | 338 | |
339 | 339 | pthread_mutex_unlock(&monitor); |
340 | 340 | |
341 | - metrics_wake_event(WAKE_EVENT_RELEASED, NULL, WAKE_LOCK_ID, now_ms); | |
341 | + metrics_log_wake_event(WAKE_EVENT_RELEASED, "", "", now_ms); | |
342 | 342 | } |
343 | 343 | |
344 | 344 | void wakelock_debug_dump(int fd) { |
@@ -0,0 +1,242 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2016 Google, Inc. | |
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 | +#include <gmock/gmock.h> | |
19 | +#include <gtest/gtest.h> | |
20 | + | |
21 | +#include <base/logging.h> | |
22 | + | |
23 | +#include "osi/include/leaky_bonded_queue.h" | |
24 | + | |
25 | +namespace testing { | |
26 | + | |
27 | +using system_bt_osi::LeakyBondedQueue; | |
28 | + | |
29 | +#define ITEM_EQ(a, b) \ | |
30 | + do { \ | |
31 | + EXPECT_EQ(a, b); \ | |
32 | + EXPECT_EQ(a->index, b->index); \ | |
33 | + } while (0) | |
34 | + | |
35 | +class Item { | |
36 | + public: | |
37 | + Item(int i) { index = i; } | |
38 | + virtual ~Item() {} | |
39 | + int index; | |
40 | +}; | |
41 | + | |
42 | +class MockItem : public Item { | |
43 | + public: | |
44 | + MockItem(int i) : Item(i) {} | |
45 | + ~MockItem() { Destruct(); } | |
46 | + MOCK_METHOD0(Destruct, void()); | |
47 | +}; | |
48 | + | |
49 | +TEST(LeakyBondedQueueTest, TestEnqueueDequeue) { | |
50 | + MockItem* item1 = new MockItem(1); | |
51 | + MockItem* item2 = new MockItem(2); | |
52 | + MockItem* item3 = new MockItem(3); | |
53 | + MockItem* item4 = new MockItem(4); | |
54 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(3); | |
55 | + EXPECT_EQ(queue->Capacity(), static_cast<size_t>(3)); | |
56 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
57 | + queue->Enqueue(item1); | |
58 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
59 | + queue->Enqueue(item2); | |
60 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
61 | + queue->Enqueue(item3); | |
62 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(3)); | |
63 | + EXPECT_CALL(*item1, Destruct()).Times(1); | |
64 | + queue->Enqueue(item4); | |
65 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(3)); | |
66 | + MockItem* item2_2 = queue->Dequeue(); | |
67 | + MockItem* item3_3 = queue->Dequeue(); | |
68 | + MockItem* item4_4 = queue->Dequeue(); | |
69 | + EXPECT_THAT(item2_2, NotNull()); | |
70 | + ITEM_EQ(item2_2, item2); | |
71 | + EXPECT_THAT(item3_3, NotNull()); | |
72 | + ITEM_EQ(item3_3, item3); | |
73 | + EXPECT_THAT(item4_4, NotNull()); | |
74 | + ITEM_EQ(item4_4, item4); | |
75 | + LOG(INFO) << "All done release items"; | |
76 | + EXPECT_CALL(*item2_2, Destruct()).Times(1); | |
77 | + delete item2_2; | |
78 | + EXPECT_CALL(*item3_3, Destruct()).Times(1); | |
79 | + delete item3_3; | |
80 | + EXPECT_CALL(*item4_4, Destruct()).Times(1); | |
81 | + delete item4_4; | |
82 | + delete queue; | |
83 | +} | |
84 | + | |
85 | +TEST(LeakyBondedQueueTest, TestEnqueueDequeue2) { | |
86 | + MockItem* item1 = new MockItem(1); | |
87 | + MockItem* item2 = new MockItem(2); | |
88 | + MockItem* item3 = new MockItem(3); | |
89 | + MockItem* item4 = new MockItem(4); | |
90 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); | |
91 | + EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); | |
92 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
93 | + queue->Enqueue(item1); | |
94 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
95 | + MockItem* item1_1 = queue->Dequeue(); | |
96 | + ITEM_EQ(item1, item1_1); | |
97 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
98 | + queue->Enqueue(item2); | |
99 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
100 | + queue->Enqueue(item3); | |
101 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
102 | + EXPECT_CALL(*item2, Destruct()).Times(1); | |
103 | + queue->Enqueue(item4); | |
104 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
105 | + EXPECT_CALL(*item3, Destruct()).Times(1); | |
106 | + queue->Enqueue(item1); | |
107 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
108 | + MockItem* item4_4_4 = queue->Dequeue(); | |
109 | + MockItem* item1_1_1 = queue->Dequeue(); | |
110 | + ITEM_EQ(item4_4_4, item4); | |
111 | + ITEM_EQ(item1_1_1, item1); | |
112 | + EXPECT_CALL(*item1_1_1, Destruct()).Times(1); | |
113 | + delete item1_1_1; | |
114 | + EXPECT_CALL(*item4_4_4, Destruct()).Times(1); | |
115 | + delete item4_4_4; | |
116 | + delete queue; | |
117 | +} | |
118 | + | |
119 | +TEST(LeakyBondedQueueTest, TestEnqueuePop) { | |
120 | + MockItem* item1 = new MockItem(1); | |
121 | + MockItem* item2 = new MockItem(2); | |
122 | + MockItem* item3 = new MockItem(3); | |
123 | + MockItem* item4 = new MockItem(4); | |
124 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); | |
125 | + EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); | |
126 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
127 | + queue->Enqueue(item1); | |
128 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
129 | + MockItem* item1_1 = queue->Dequeue(); | |
130 | + ITEM_EQ(item1, item1_1); | |
131 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
132 | + queue->Enqueue(item2); | |
133 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
134 | + queue->Enqueue(item3); | |
135 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
136 | + MockItem* item2_2 = queue->EnqueueWithPop(item4); | |
137 | + EXPECT_THAT(item2_2, NotNull()); | |
138 | + ITEM_EQ(item2_2, item2); | |
139 | + EXPECT_CALL(*item2, Destruct()).Times(1); | |
140 | + delete item2_2; | |
141 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
142 | + MockItem* item3_3 = queue->EnqueueWithPop(item1); | |
143 | + EXPECT_THAT(item3_3, NotNull()); | |
144 | + ITEM_EQ(item3_3, item3); | |
145 | + EXPECT_CALL(*item3, Destruct()).Times(1); | |
146 | + delete item3_3; | |
147 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
148 | + MockItem* item4_4_4 = queue->Dequeue(); | |
149 | + MockItem* item1_1_1 = queue->Dequeue(); | |
150 | + ITEM_EQ(item4_4_4, item4); | |
151 | + ITEM_EQ(item1_1_1, item1); | |
152 | + EXPECT_CALL(*item1_1_1, Destruct()).Times(1); | |
153 | + delete item1_1_1; | |
154 | + EXPECT_CALL(*item4_4_4, Destruct()).Times(1); | |
155 | + delete item4_4_4; | |
156 | + delete queue; | |
157 | +} | |
158 | + | |
159 | +TEST(LeakyBondedQueueTest, TestQueueClear) { | |
160 | + MockItem* item1 = new MockItem(1); | |
161 | + MockItem* item2 = new MockItem(2); | |
162 | + MockItem* item3 = new MockItem(3); | |
163 | + MockItem* item4 = new MockItem(4); | |
164 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); | |
165 | + EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); | |
166 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
167 | + queue->Enqueue(item1); | |
168 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
169 | + MockItem* item1_1 = queue->Dequeue(); | |
170 | + ITEM_EQ(item1, item1_1); | |
171 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
172 | + queue->Enqueue(item2); | |
173 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
174 | + queue->Enqueue(item3); | |
175 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
176 | + EXPECT_CALL(*item2, Destruct()).Times(1); | |
177 | + queue->Enqueue(item4); | |
178 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
179 | + EXPECT_CALL(*item3, Destruct()).Times(1); | |
180 | + queue->Enqueue(item1); | |
181 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
182 | + EXPECT_CALL(*item1, Destruct()).Times(1); | |
183 | + EXPECT_CALL(*item4, Destruct()).Times(1); | |
184 | + queue->Clear(); | |
185 | + delete queue; | |
186 | +} | |
187 | + | |
188 | +TEST(LeakyBondedQueueTest, TestQueueFree) { | |
189 | + MockItem* item1 = new MockItem(1); | |
190 | + MockItem* item2 = new MockItem(2); | |
191 | + MockItem* item3 = new MockItem(3); | |
192 | + MockItem* item4 = new MockItem(4); | |
193 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); | |
194 | + EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2)); | |
195 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
196 | + queue->Enqueue(item1); | |
197 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
198 | + MockItem* item1_1 = queue->Dequeue(); | |
199 | + ITEM_EQ(item1, item1_1); | |
200 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(0)); | |
201 | + queue->Enqueue(item2); | |
202 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(1)); | |
203 | + queue->Enqueue(item3); | |
204 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
205 | + EXPECT_CALL(*item2, Destruct()).Times(1); | |
206 | + queue->Enqueue(item4); | |
207 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
208 | + EXPECT_CALL(*item3, Destruct()).Times(1); | |
209 | + queue->Enqueue(item1); | |
210 | + EXPECT_EQ(queue->Length(), static_cast<size_t>(2)); | |
211 | + EXPECT_CALL(*item1, Destruct()).Times(1); | |
212 | + EXPECT_CALL(*item4, Destruct()).Times(1); | |
213 | + delete queue; | |
214 | +} | |
215 | + | |
216 | +TEST(LeakyBondedQueueTest, TestPushNull) { | |
217 | + MockItem* item1 = nullptr; | |
218 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); | |
219 | + queue->Enqueue(item1); | |
220 | + MockItem* item1_1 = queue->Dequeue(); | |
221 | + EXPECT_THAT(item1_1, IsNull()); | |
222 | +} | |
223 | + | |
224 | +TEST(LeakyBondedQueueTest, TestPushNullOverflowQueue) { | |
225 | + MockItem* item1 = nullptr; | |
226 | + MockItem* item2 = nullptr; | |
227 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(1); | |
228 | + queue->Enqueue(item1); | |
229 | + queue->Enqueue(item2); | |
230 | + MockItem* item2_2 = queue->Dequeue(); | |
231 | + EXPECT_THAT(item2_2, IsNull()); | |
232 | +} | |
233 | + | |
234 | +TEST(LeakyBondedQueueTest, TestPushNullDeleteQueue) { | |
235 | + MockItem* item1 = nullptr; | |
236 | + MockItem* item2 = nullptr; | |
237 | + LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2); | |
238 | + queue->Enqueue(item1); | |
239 | + queue->Enqueue(item2); | |
240 | + delete queue; | |
241 | +} | |
242 | +} |
@@ -0,0 +1,805 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Copyright (C) 2016 Google, Inc. | |
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 | +#include <chrono> | |
19 | +#include <cstdint> | |
20 | +#include <string> | |
21 | +#include <thread> | |
22 | +#include <vector> | |
23 | + | |
24 | +#include <gmock/gmock.h> | |
25 | +#include <gtest/gtest.h> | |
26 | + | |
27 | +#include <base/logging.h> | |
28 | + | |
29 | +#include "osi/include/metrics.h" | |
30 | +#include "osi/include/metrics_cpp.h" | |
31 | +#include "osi/include/time.h" | |
32 | +#include "osi/src/protos/bluetooth.pb.h" | |
33 | + | |
34 | +#define BTM_COD_MAJOR_AUDIO_TEST 0x04 | |
35 | + | |
36 | +namespace testing { | |
37 | + | |
38 | +using clearcut::connectivity::A2DPSession; | |
39 | +using clearcut::connectivity::BluetoothLog; | |
40 | +using clearcut::connectivity::BluetoothSession; | |
41 | +using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType; | |
42 | +using clearcut::connectivity::BluetoothSession_DisconnectReasonType; | |
43 | +using clearcut::connectivity::DeviceInfo; | |
44 | +using clearcut::connectivity::DeviceInfo_DeviceType; | |
45 | +using clearcut::connectivity::PairEvent; | |
46 | +using clearcut::connectivity::RFCommSession; | |
47 | +using clearcut::connectivity::ScanEvent; | |
48 | +using clearcut::connectivity::ScanEvent_ScanTechnologyType; | |
49 | +using clearcut::connectivity::ScanEvent_ScanEventType; | |
50 | +using clearcut::connectivity::WakeEvent; | |
51 | +using clearcut::connectivity::WakeEvent_WakeEventType; | |
52 | +using system_bt_osi::BluetoothMetricsLogger; | |
53 | +using system_bt_osi::A2dpSessionMetrics; | |
54 | + | |
55 | +namespace { | |
56 | +const size_t kMaxEventGenerationLimit = 5000; | |
57 | +} | |
58 | + | |
59 | +uint64_t metrics_time_get_os_boottime_us(void) { | |
60 | + struct timespec ts_now; | |
61 | + clock_gettime(CLOCK_BOOTTIME, &ts_now); | |
62 | + | |
63 | + return ((uint64_t)ts_now.tv_sec * 1000000L) + | |
64 | + ((uint64_t)ts_now.tv_nsec / 1000); | |
65 | +} | |
66 | + | |
67 | +/* | |
68 | + * Get current OS boot time in millisecond | |
69 | + */ | |
70 | +static int64_t time_get_os_boottime_ms(void) { | |
71 | + return metrics_time_get_os_boottime_us() / 1000; | |
72 | +} | |
73 | + | |
74 | +static void sleep_ms(int64_t t) { | |
75 | + std::this_thread::sleep_for(std::chrono::milliseconds(t)); | |
76 | +} | |
77 | + | |
78 | +DeviceInfo* MakeDeviceInfo(int32_t device_class, | |
79 | + DeviceInfo_DeviceType device_type) { | |
80 | + DeviceInfo* info = new DeviceInfo(); | |
81 | + info->set_device_class(device_class); | |
82 | + info->set_device_type(device_type); | |
83 | + return info; | |
84 | +} | |
85 | + | |
86 | +PairEvent* MakePairEvent(int32_t disconnect_reason, int64_t timestamp_ms, | |
87 | + DeviceInfo* device_info) { | |
88 | + PairEvent* event = new PairEvent(); | |
89 | + event->set_disconnect_reason(disconnect_reason); | |
90 | + event->set_event_time_millis(timestamp_ms); | |
91 | + if (device_info) event->set_allocated_device_paired_with(device_info); | |
92 | + return event; | |
93 | +} | |
94 | + | |
95 | +WakeEvent* MakeWakeEvent(WakeEvent_WakeEventType event_type, | |
96 | + const std::string& requestor, const std::string& name, | |
97 | + int64_t timestamp_ms) { | |
98 | + WakeEvent* event = new WakeEvent(); | |
99 | + event->set_wake_event_type(event_type); | |
100 | + event->set_requestor(requestor); | |
101 | + event->set_name(name); | |
102 | + event->set_event_time_millis(timestamp_ms); | |
103 | + return event; | |
104 | +} | |
105 | + | |
106 | +ScanEvent* MakeScanEvent(ScanEvent_ScanEventType event_type, | |
107 | + const std::string& initiator, | |
108 | + ScanEvent_ScanTechnologyType tech_type, | |
109 | + int32_t num_results, int64_t timestamp_ms) { | |
110 | + ScanEvent* event = new ScanEvent(); | |
111 | + event->set_scan_event_type(event_type); | |
112 | + event->set_initiator(initiator); | |
113 | + event->set_scan_technology_type(tech_type); | |
114 | + event->set_number_results(num_results); | |
115 | + event->set_event_time_millis(timestamp_ms); | |
116 | + return event; | |
117 | +} | |
118 | + | |
119 | +A2DPSession* MakeA2DPSession(const A2dpSessionMetrics& metrics) { | |
120 | + A2DPSession* session = new A2DPSession(); | |
121 | + session->set_media_timer_min_millis(metrics.media_timer_min_ms); | |
122 | + session->set_media_timer_max_millis(metrics.media_timer_max_ms); | |
123 | + session->set_media_timer_avg_millis(metrics.media_timer_avg_ms); | |
124 | + session->set_buffer_overruns_max_count(metrics.buffer_overruns_max_count); | |
125 | + session->set_buffer_overruns_total(metrics.buffer_overruns_total); | |
126 | + session->set_buffer_underruns_average(metrics.buffer_underruns_average); | |
127 | + session->set_buffer_underruns_count(metrics.buffer_underruns_count); | |
128 | + session->set_audio_duration_millis(metrics.audio_duration_ms); | |
129 | + return session; | |
130 | +} | |
131 | + | |
132 | +BluetoothSession* MakeBluetoothSession( | |
133 | + int64_t session_duration_sec, | |
134 | + BluetoothSession_ConnectionTechnologyType conn_type, | |
135 | + BluetoothSession_DisconnectReasonType disconnect_reason, | |
136 | + DeviceInfo* device_info, RFCommSession* rfcomm_session, | |
137 | + A2DPSession* a2dp_session) { | |
138 | + BluetoothSession* session = new BluetoothSession(); | |
139 | + if (a2dp_session) session->set_allocated_a2dp_session(a2dp_session); | |
140 | + if (rfcomm_session) session->set_allocated_rfcomm_session(rfcomm_session); | |
141 | + if (device_info) session->set_allocated_device_connected_to(device_info); | |
142 | + session->set_session_duration_sec(session_duration_sec); | |
143 | + session->set_connection_technology_type(conn_type); | |
144 | + session->set_disconnect_reason_type(disconnect_reason); | |
145 | + return session; | |
146 | +} | |
147 | + | |
148 | +BluetoothLog* MakeBluetoothLog(std::vector<BluetoothSession*> bt_sessions, | |
149 | + std::vector<PairEvent*> pair_events, | |
150 | + std::vector<WakeEvent*> wake_events, | |
151 | + std::vector<ScanEvent*> scan_events) { | |
152 | + BluetoothLog* bt_log = new BluetoothLog(); | |
153 | + for (BluetoothSession* session : bt_sessions) { | |
154 | + bt_log->mutable_session()->AddAllocated(session); | |
155 | + } | |
156 | + bt_sessions.clear(); | |
157 | + for (PairEvent* event : pair_events) { | |
158 | + bt_log->mutable_pair_event()->AddAllocated(event); | |
159 | + } | |
160 | + pair_events.clear(); | |
161 | + for (WakeEvent* event : wake_events) { | |
162 | + bt_log->mutable_wake_event()->AddAllocated(event); | |
163 | + } | |
164 | + wake_events.clear(); | |
165 | + for (ScanEvent* event : scan_events) { | |
166 | + bt_log->mutable_scan_event()->AddAllocated(event); | |
167 | + } | |
168 | + scan_events.clear(); | |
169 | + return bt_log; | |
170 | +} | |
171 | + | |
172 | +void GenerateWakeEvents(size_t start, size_t end, | |
173 | + std::vector<WakeEvent*>* wake_events) { | |
174 | + for (size_t i = start; i < end; ++i) { | |
175 | + wake_events->push_back(MakeWakeEvent( | |
176 | + i % 2 == 0 ? WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED | |
177 | + : WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED, | |
178 | + "TEST_REQ", "TEST_NAME", i)); | |
179 | + } | |
180 | +} | |
181 | + | |
182 | +#define COMPARE_A2DP_METRICS(a, b) \ | |
183 | + do { \ | |
184 | + EXPECT_EQ(a.audio_duration_ms, b.audio_duration_ms); \ | |
185 | + EXPECT_EQ(a.media_timer_min_ms, b.media_timer_min_ms); \ | |
186 | + EXPECT_EQ(a.media_timer_max_ms, b.media_timer_max_ms); \ | |
187 | + EXPECT_EQ(a.media_timer_avg_ms, b.media_timer_avg_ms); \ | |
188 | + EXPECT_EQ(a.total_scheduling_count, b.total_scheduling_count); \ | |
189 | + EXPECT_EQ(a.buffer_overruns_max_count, b.buffer_overruns_max_count); \ | |
190 | + EXPECT_EQ(a.buffer_overruns_total, b.buffer_overruns_total); \ | |
191 | + EXPECT_THAT(a.buffer_underruns_average, \ | |
192 | + FloatNear(b.buffer_underruns_average, 0.01)); \ | |
193 | + a.buffer_underruns_average = b.buffer_underruns_average; \ | |
194 | + EXPECT_EQ(a.buffer_underruns_count, b.buffer_underruns_count); \ | |
195 | + } while (0) | |
196 | + | |
197 | +/* | |
198 | + * metrics_sum = metrics1 + metrics2 | |
199 | + */ | |
200 | +TEST(BluetoothA2DPSessionMetricsTest, TestUpdateNormal) { | |
201 | + A2dpSessionMetrics metrics1; | |
202 | + A2dpSessionMetrics metrics2; | |
203 | + A2dpSessionMetrics metrics_sum; | |
204 | + metrics1.audio_duration_ms = 10; | |
205 | + metrics2.audio_duration_ms = 25; | |
206 | + metrics_sum.audio_duration_ms = 35; | |
207 | + metrics1.media_timer_min_ms = 10; | |
208 | + metrics2.media_timer_min_ms = 25; | |
209 | + metrics_sum.media_timer_min_ms = 10; | |
210 | + metrics1.media_timer_max_ms = 100; | |
211 | + metrics2.media_timer_max_ms = 200; | |
212 | + metrics_sum.media_timer_max_ms = 200; | |
213 | + metrics1.media_timer_avg_ms = 50; | |
214 | + metrics1.total_scheduling_count = 50; | |
215 | + metrics2.media_timer_avg_ms = 100; | |
216 | + metrics2.total_scheduling_count = 50; | |
217 | + metrics_sum.media_timer_avg_ms = 75; | |
218 | + metrics_sum.total_scheduling_count = 100; | |
219 | + metrics1.buffer_overruns_max_count = 70; | |
220 | + metrics2.buffer_overruns_max_count = 80; | |
221 | + metrics_sum.buffer_overruns_max_count = 80; | |
222 | + metrics1.buffer_underruns_average = 80; | |
223 | + metrics1.buffer_underruns_count = 1200; | |
224 | + metrics2.buffer_underruns_average = 130; | |
225 | + metrics2.buffer_underruns_count = 2400; | |
226 | + metrics_sum.buffer_underruns_average = 113.33333333; | |
227 | + metrics_sum.buffer_underruns_count = 3600; | |
228 | + metrics1.Update(metrics2); | |
229 | + COMPARE_A2DP_METRICS(metrics1, metrics_sum); | |
230 | + EXPECT_TRUE(metrics1 == metrics_sum); | |
231 | + EXPECT_EQ(metrics1, metrics_sum); | |
232 | +} | |
233 | + | |
234 | +TEST(BluetoothA2DPSessionMetricsTest, TestUpdateNew) { | |
235 | + A2dpSessionMetrics metrics1; | |
236 | + A2dpSessionMetrics metrics2; | |
237 | + A2dpSessionMetrics metrics_sum; | |
238 | + metrics2.audio_duration_ms = 25; | |
239 | + metrics_sum.audio_duration_ms = 25; | |
240 | + metrics2.media_timer_min_ms = 25; | |
241 | + metrics_sum.media_timer_min_ms = 25; | |
242 | + metrics2.media_timer_max_ms = 200; | |
243 | + metrics_sum.media_timer_max_ms = 200; | |
244 | + metrics2.media_timer_avg_ms = 100; | |
245 | + metrics2.total_scheduling_count = 50; | |
246 | + metrics_sum.media_timer_avg_ms = 100; | |
247 | + metrics_sum.total_scheduling_count = 50; | |
248 | + metrics2.buffer_overruns_max_count = 80; | |
249 | + metrics_sum.buffer_overruns_max_count = 80; | |
250 | + metrics2.buffer_underruns_average = 130; | |
251 | + metrics2.buffer_underruns_count = 2400; | |
252 | + metrics_sum.buffer_underruns_average = 130; | |
253 | + metrics_sum.buffer_underruns_count = 2400; | |
254 | + metrics1.Update(metrics2); | |
255 | + COMPARE_A2DP_METRICS(metrics1, metrics_sum); | |
256 | + EXPECT_TRUE(metrics1 == metrics_sum); | |
257 | + EXPECT_EQ(metrics1, metrics_sum); | |
258 | +} | |
259 | + | |
260 | +TEST(BluetoothA2DPSessionMetricsTest, TestNullUpdate) { | |
261 | + A2dpSessionMetrics metrics1; | |
262 | + A2dpSessionMetrics metrics2; | |
263 | + A2dpSessionMetrics metrics_sum; | |
264 | + metrics2.audio_duration_ms = 25; | |
265 | + metrics_sum.audio_duration_ms = 25; | |
266 | + metrics2.media_timer_min_ms = 25; | |
267 | + metrics_sum.media_timer_min_ms = 25; | |
268 | + metrics2.media_timer_max_ms = 200; | |
269 | + metrics_sum.media_timer_max_ms = 200; | |
270 | + metrics2.media_timer_avg_ms = 100; | |
271 | + metrics2.total_scheduling_count = 50; | |
272 | + metrics_sum.media_timer_avg_ms = 100; | |
273 | + metrics_sum.total_scheduling_count = 50; | |
274 | + metrics2.buffer_overruns_max_count = 80; | |
275 | + metrics_sum.buffer_overruns_max_count = 80; | |
276 | + metrics2.buffer_underruns_average = 130; | |
277 | + metrics2.buffer_underruns_count = 2400; | |
278 | + metrics_sum.buffer_underruns_average = 130; | |
279 | + metrics_sum.buffer_underruns_count = 2400; | |
280 | + metrics2.Update(metrics1); | |
281 | + COMPARE_A2DP_METRICS(metrics2, metrics_sum); | |
282 | + EXPECT_TRUE(metrics2 == metrics_sum); | |
283 | + EXPECT_EQ(metrics2, metrics_sum); | |
284 | +} | |
285 | + | |
286 | +TEST(BluetoothA2DPSessionMetricsTest, TestPartialUpdate) { | |
287 | + A2dpSessionMetrics metrics1; | |
288 | + A2dpSessionMetrics metrics2; | |
289 | + A2dpSessionMetrics metrics_sum; | |
290 | + metrics1.audio_duration_ms = 10; | |
291 | + metrics2.audio_duration_ms = 25; | |
292 | + metrics_sum.audio_duration_ms = 35; | |
293 | + metrics1.media_timer_min_ms = 10; | |
294 | + metrics_sum.media_timer_min_ms = 10; | |
295 | + metrics1.media_timer_max_ms = 100; | |
296 | + metrics_sum.media_timer_max_ms = 100; | |
297 | + metrics1.media_timer_avg_ms = 50; | |
298 | + metrics1.total_scheduling_count = 50; | |
299 | + metrics2.media_timer_avg_ms = 100; | |
300 | + metrics_sum.media_timer_avg_ms = 50; | |
301 | + metrics_sum.total_scheduling_count = 50; | |
302 | + metrics1.buffer_overruns_max_count = 70; | |
303 | + metrics_sum.buffer_overruns_max_count = 70; | |
304 | + metrics1.buffer_underruns_average = 80; | |
305 | + metrics1.buffer_underruns_count = 1200; | |
306 | + metrics2.buffer_underruns_count = 2400; | |
307 | + metrics_sum.buffer_underruns_average = 80; | |
308 | + metrics_sum.buffer_underruns_count = 1200; | |
309 | + metrics1.Update(metrics2); | |
310 | + COMPARE_A2DP_METRICS(metrics1, metrics_sum); | |
311 | + EXPECT_TRUE(metrics1 == metrics_sum); | |
312 | + EXPECT_EQ(metrics1, metrics_sum); | |
313 | +} | |
314 | + | |
315 | +class BluetoothMetricsLoggerTest : public Test { | |
316 | + protected: | |
317 | + // Use to hold test protos | |
318 | + std::vector<PairEvent*> pair_events_; | |
319 | + std::vector<WakeEvent*> wake_events_; | |
320 | + std::vector<ScanEvent*> scan_events_; | |
321 | + std::vector<BluetoothSession*> bt_sessions_; | |
322 | + int64_t num_pair_event_ = 0; | |
323 | + int64_t num_wake_event_ = 0; | |
324 | + int64_t num_scan_event_ = 0; | |
325 | + int64_t num_bt_session_ = 0; | |
326 | + BluetoothLog* bt_log_; | |
327 | + std::string bt_log_str_; | |
328 | + std::string bt_log_ascii_str_; | |
329 | + | |
330 | + void UpdateLog() { | |
331 | + for (BluetoothSession* session : bt_sessions_) { | |
332 | + bt_log_->mutable_session()->AddAllocated(session); | |
333 | + } | |
334 | + if (num_bt_session_ > 0) { | |
335 | + bt_log_->set_num_bluetooth_session(num_bt_session_); | |
336 | + } else if (bt_sessions_.size() > 0) { | |
337 | + bt_log_->set_num_bluetooth_session(bt_sessions_.size()); | |
338 | + } | |
339 | + bt_sessions_.clear(); | |
340 | + for (PairEvent* event : pair_events_) { | |
341 | + bt_log_->mutable_pair_event()->AddAllocated(event); | |
342 | + } | |
343 | + if (num_pair_event_ > 0) { | |
344 | + bt_log_->set_num_pair_event(num_pair_event_); | |
345 | + } else if (pair_events_.size() > 0) { | |
346 | + bt_log_->set_num_pair_event(pair_events_.size()); | |
347 | + } | |
348 | + pair_events_.clear(); | |
349 | + for (WakeEvent* event : wake_events_) { | |
350 | + bt_log_->mutable_wake_event()->AddAllocated(event); | |
351 | + } | |
352 | + if (num_wake_event_ > 0) { | |
353 | + bt_log_->set_num_wake_event(num_wake_event_); | |
354 | + } else if (wake_events_.size() > 0) { | |
355 | + bt_log_->set_num_wake_event(wake_events_.size()); | |
356 | + } | |
357 | + wake_events_.clear(); | |
358 | + for (ScanEvent* event : scan_events_) { | |
359 | + bt_log_->mutable_scan_event()->AddAllocated(event); | |
360 | + } | |
361 | + if (num_scan_event_ > 0) { | |
362 | + bt_log_->set_num_scan_event(num_scan_event_); | |
363 | + } else if (scan_events_.size() > 0) { | |
364 | + bt_log_->set_num_scan_event(scan_events_.size()); | |
365 | + } | |
366 | + scan_events_.clear(); | |
367 | + bt_log_->SerializeToString(&bt_log_str_); | |
368 | + } | |
369 | + | |
370 | + void ClearLog() { | |
371 | + for (BluetoothSession* session : bt_sessions_) { | |
372 | + session->Clear(); | |
373 | + delete session; | |
374 | + } | |
375 | + bt_sessions_.clear(); | |
376 | + for (PairEvent* event : pair_events_) { | |
377 | + event->Clear(); | |
378 | + delete event; | |
379 | + } | |
380 | + pair_events_.clear(); | |
381 | + for (WakeEvent* event : wake_events_) { | |
382 | + event->Clear(); | |
383 | + delete event; | |
384 | + } | |
385 | + wake_events_.clear(); | |
386 | + for (ScanEvent* event : scan_events_) { | |
387 | + event->Clear(); | |
388 | + delete event; | |
389 | + } | |
390 | + scan_events_.clear(); | |
391 | + bt_log_->Clear(); | |
392 | + } | |
393 | + | |
394 | + void SetUp() { | |
395 | + bt_log_ = new BluetoothLog(); | |
396 | + // Clear existing metrics entries, if any | |
397 | + BluetoothMetricsLogger::GetInstance()->Reset(); | |
398 | + } | |
399 | + void TearDown() { | |
400 | + // Clear remaining metrics entries, if any | |
401 | + BluetoothMetricsLogger::GetInstance()->Reset(); | |
402 | + ClearLog(); | |
403 | + delete bt_log_; | |
404 | + } | |
405 | + | |
406 | + public: | |
407 | +}; | |
408 | + | |
409 | +TEST_F(BluetoothMetricsLoggerTest, PairEventTest) { | |
410 | + pair_events_.push_back(MakePairEvent( | |
411 | + 35, 12345, | |
412 | + MakeDeviceInfo( | |
413 | + 42, DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR))); | |
414 | + UpdateLog(); | |
415 | + BluetoothMetricsLogger::GetInstance()->LogPairEvent( | |
416 | + 35, 12345, 42, DEVICE_TYPE_BREDR); | |
417 | + std::string msg_str; | |
418 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
419 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
420 | +} | |
421 | + | |
422 | +TEST_F(BluetoothMetricsLoggerTest, WakeEventTest) { | |
423 | + wake_events_.push_back( | |
424 | + MakeWakeEvent(WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED, | |
425 | + "TEST_REQ", "TEST_NAME", 12345)); | |
426 | + UpdateLog(); | |
427 | + BluetoothMetricsLogger::GetInstance()->LogWakeEvent( | |
428 | + WAKE_EVENT_ACQUIRED, "TEST_REQ", "TEST_NAME", 12345); | |
429 | + std::string msg_str; | |
430 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
431 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
432 | +} | |
433 | + | |
434 | +TEST_F(BluetoothMetricsLoggerTest, WakeEventOverrunTest) { | |
435 | + GenerateWakeEvents(kMaxEventGenerationLimit - | |
436 | + BluetoothMetricsLogger::kMaxNumWakeEvent, | |
437 | + kMaxEventGenerationLimit, &wake_events_); | |
438 | + num_wake_event_ = kMaxEventGenerationLimit; | |
439 | + UpdateLog(); | |
440 | + for (size_t i = 0; i < kMaxEventGenerationLimit; ++i) { | |
441 | + BluetoothMetricsLogger::GetInstance()->LogWakeEvent( | |
442 | + i % 2 == 0 ? WAKE_EVENT_ACQUIRED : WAKE_EVENT_RELEASED, | |
443 | + "TEST_REQ", "TEST_NAME", i); | |
444 | + } | |
445 | + std::string msg_str; | |
446 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
447 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
448 | +} | |
449 | + | |
450 | +TEST_F(BluetoothMetricsLoggerTest, ScanEventTest) { | |
451 | + scan_events_.push_back(MakeScanEvent( | |
452 | + ScanEvent_ScanEventType::ScanEvent_ScanEventType_SCAN_EVENT_STOP, | |
453 | + "TEST_INITIATOR", ScanEvent_ScanTechnologyType:: | |
454 | + ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR, | |
455 | + 42, 123456)); | |
456 | + UpdateLog(); | |
457 | + BluetoothMetricsLogger::GetInstance()->LogScanEvent( | |
458 | + false, "TEST_INITIATOR", SCAN_TECH_TYPE_BREDR, 42, 123456); | |
459 | + std::string msg_str; | |
460 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
461 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
462 | +} | |
463 | + | |
464 | +TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionTest) { | |
465 | + bt_sessions_.push_back(MakeBluetoothSession( | |
466 | + 10, | |
467 | + BluetoothSession_ConnectionTechnologyType:: | |
468 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE, | |
469 | + BluetoothSession_DisconnectReasonType:: | |
470 | + BluetoothSession_DisconnectReasonType_UNKNOWN, | |
471 | + nullptr, nullptr, nullptr)); | |
472 | + UpdateLog(); | |
473 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
474 | + CONNECTION_TECHNOLOGY_TYPE_LE, 123456); | |
475 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( | |
476 | + DISCONNECT_REASON_UNKNOWN, 133456); | |
477 | + std::string msg_str; | |
478 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
479 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
480 | +} | |
481 | + | |
482 | +TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionDumpBeforeEndTest) { | |
483 | + bt_sessions_.push_back(MakeBluetoothSession( | |
484 | + 1, | |
485 | + BluetoothSession_ConnectionTechnologyType:: | |
486 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE, | |
487 | + BluetoothSession_DisconnectReasonType:: | |
488 | + BluetoothSession_DisconnectReasonType_METRICS_DUMP, | |
489 | + nullptr, nullptr, nullptr)); | |
490 | + UpdateLog(); | |
491 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
492 | + CONNECTION_TECHNOLOGY_TYPE_LE, time_get_os_boottime_ms()); | |
493 | + sleep_ms(1000); | |
494 | + std::string msg_str; | |
495 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
496 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
497 | +} | |
498 | + | |
499 | +TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionStartBeforeEndTest) { | |
500 | + bt_sessions_.push_back(MakeBluetoothSession( | |
501 | + 1, | |
502 | + BluetoothSession_ConnectionTechnologyType:: | |
503 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, | |
504 | + BluetoothSession_DisconnectReasonType:: | |
505 | + BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS, | |
506 | + nullptr, nullptr, nullptr)); | |
507 | + bt_sessions_.push_back(MakeBluetoothSession( | |
508 | + 2, | |
509 | + BluetoothSession_ConnectionTechnologyType:: | |
510 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE, | |
511 | + BluetoothSession_DisconnectReasonType:: | |
512 | + BluetoothSession_DisconnectReasonType_METRICS_DUMP, | |
513 | + nullptr, nullptr, nullptr)); | |
514 | + UpdateLog(); | |
515 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
516 | + CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0); | |
517 | + sleep_ms(1000); | |
518 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
519 | + CONNECTION_TECHNOLOGY_TYPE_LE, 0); | |
520 | + sleep_ms(2000); | |
521 | + std::string msg_str; | |
522 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
523 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
524 | +} | |
525 | + | |
526 | +/* | |
527 | + * Test Case: A2DPSessionTwoUpdatesTest | |
528 | + * | |
529 | + * 1. Create Instance | |
530 | + * 2. LogBluetoothSessionStart | |
531 | + * 3. LogBluetoothSessionDeviceInfo | |
532 | + * 4. LogA2dpSession | |
533 | + * 5. LogA2dpSession | |
534 | + * 6. LogBluetoothSessionEnd | |
535 | + * 7. WriteString | |
536 | + * | |
537 | + */ | |
538 | +TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesTest) { | |
539 | + /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ | |
540 | + A2dpSessionMetrics metrics1; | |
541 | + A2dpSessionMetrics metrics2; | |
542 | + A2dpSessionMetrics metrics_sum; | |
543 | + metrics1.audio_duration_ms = 10; | |
544 | + metrics2.audio_duration_ms = 25; | |
545 | + metrics_sum.audio_duration_ms = 35; | |
546 | + metrics1.media_timer_min_ms = 10; | |
547 | + metrics2.media_timer_min_ms = 25; | |
548 | + metrics_sum.media_timer_min_ms = 10; | |
549 | + metrics1.media_timer_max_ms = 100; | |
550 | + metrics2.media_timer_max_ms = 200; | |
551 | + metrics_sum.media_timer_max_ms = 200; | |
552 | + metrics1.media_timer_avg_ms = 50; | |
553 | + metrics1.total_scheduling_count = 50; | |
554 | + metrics2.media_timer_avg_ms = 100; | |
555 | + metrics2.total_scheduling_count = 50; | |
556 | + metrics_sum.media_timer_avg_ms = 75; | |
557 | + metrics_sum.total_scheduling_count = 100; | |
558 | + metrics1.buffer_overruns_max_count = 70; | |
559 | + metrics2.buffer_overruns_max_count = 80; | |
560 | + metrics_sum.buffer_overruns_max_count = 80; | |
561 | + metrics1.buffer_underruns_average = 80; | |
562 | + metrics1.buffer_underruns_count = 1200; | |
563 | + metrics2.buffer_underruns_average = 130; | |
564 | + metrics2.buffer_underruns_count = 2400; | |
565 | + metrics_sum.buffer_underruns_average = 113.33333333; | |
566 | + metrics_sum.buffer_underruns_count = 3600; | |
567 | + DeviceInfo* info = MakeDeviceInfo( | |
568 | + BTM_COD_MAJOR_AUDIO_TEST, | |
569 | + DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); | |
570 | + A2DPSession* session = MakeA2DPSession(metrics_sum); | |
571 | + bt_sessions_.push_back(MakeBluetoothSession( | |
572 | + 10, | |
573 | + BluetoothSession_ConnectionTechnologyType:: | |
574 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
575 | + BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, | |
576 | + info, nullptr, session)); | |
577 | + UpdateLog(); | |
578 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
579 | + CONNECTION_TECHNOLOGY_TYPE_BREDR, 123456); | |
580 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( | |
581 | + BTM_COD_MAJOR_AUDIO_TEST, DEVICE_TYPE_BREDR); | |
582 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); | |
583 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); | |
584 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( | |
585 | + DISCONNECT_REASON_UNKNOWN, 133456); | |
586 | + std::string msg_str; | |
587 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
588 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
589 | +} | |
590 | + | |
591 | +/* | |
592 | + * Test Case: A2DPSessionTwoUpdatesSeparatedbyDumpTest | |
593 | + * | |
594 | + * 1. Create Instance | |
595 | + * 2. LogBluetoothSessionStart | |
596 | + * 3. LogBluetoothSessionDeviceInfo | |
597 | + * 4. LogA2dpSession | |
598 | + * 5. WriteString | |
599 | + * 6. LogA2dpSession | |
600 | + * 7. LogBluetoothSessionEnd | |
601 | + * 8. WriteString | |
602 | + * | |
603 | + */ | |
604 | +TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesSeparatedbyDumpTest) { | |
605 | + /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ | |
606 | + A2dpSessionMetrics metrics1; | |
607 | + A2dpSessionMetrics metrics2; | |
608 | + metrics1.audio_duration_ms = 10; | |
609 | + metrics2.audio_duration_ms = 25; | |
610 | + metrics1.media_timer_min_ms = 10; | |
611 | + metrics2.media_timer_min_ms = 25; | |
612 | + metrics1.media_timer_max_ms = 100; | |
613 | + metrics2.media_timer_max_ms = 200; | |
614 | + metrics1.media_timer_avg_ms = 50; | |
615 | + metrics1.total_scheduling_count = 50; | |
616 | + metrics2.media_timer_avg_ms = 100; | |
617 | + metrics2.total_scheduling_count = 50; | |
618 | + metrics1.buffer_overruns_max_count = 70; | |
619 | + metrics2.buffer_overruns_max_count = 80; | |
620 | + metrics1.buffer_underruns_average = 80; | |
621 | + metrics1.buffer_underruns_count = 1200; | |
622 | + metrics2.buffer_underruns_average = 130; | |
623 | + metrics2.buffer_underruns_count = 2400; | |
624 | + DeviceInfo* info = MakeDeviceInfo( | |
625 | + BTM_COD_MAJOR_AUDIO_TEST, | |
626 | + DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); | |
627 | + A2DPSession* session = MakeA2DPSession(metrics1); | |
628 | + bt_sessions_.push_back(MakeBluetoothSession( | |
629 | + 1, | |
630 | + BluetoothSession_ConnectionTechnologyType:: | |
631 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
632 | + BluetoothSession_DisconnectReasonType:: | |
633 | + BluetoothSession_DisconnectReasonType_METRICS_DUMP, | |
634 | + info, nullptr, session)); | |
635 | + UpdateLog(); | |
636 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
637 | + CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); | |
638 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( | |
639 | + BTM_COD_MAJOR_AUDIO_TEST, DEVICE_TYPE_BREDR); | |
640 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); | |
641 | + sleep_ms(1000); | |
642 | + std::string msg_str; | |
643 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
644 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
645 | + ClearLog(); | |
646 | + info = MakeDeviceInfo( | |
647 | + BTM_COD_MAJOR_AUDIO_TEST, | |
648 | + DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); | |
649 | + session = MakeA2DPSession(metrics2); | |
650 | + bt_sessions_.push_back(MakeBluetoothSession( | |
651 | + 1, | |
652 | + BluetoothSession_ConnectionTechnologyType:: | |
653 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
654 | + BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, | |
655 | + info, nullptr, session)); | |
656 | + UpdateLog(); | |
657 | + sleep_ms(1000); | |
658 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); | |
659 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( | |
660 | + DISCONNECT_REASON_UNKNOWN, 0); | |
661 | + msg_str.clear(); | |
662 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
663 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
664 | +} | |
665 | + | |
666 | +/* | |
667 | + * Test Case 1: A2DPSessionOnlyTest | |
668 | + * | |
669 | + * 1. Create Instance | |
670 | + * 4. LogA2dpSession | |
671 | + * 5. WriteString | |
672 | + * 6. LogA2dpSession | |
673 | + * 8. WriteString | |
674 | + * | |
675 | + */ | |
676 | +TEST_F(BluetoothMetricsLoggerTest, A2DPSessionOnlyTest) { | |
677 | + /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ | |
678 | + A2dpSessionMetrics metrics1; | |
679 | + A2dpSessionMetrics metrics2; | |
680 | + A2dpSessionMetrics metrics_sum; | |
681 | + metrics1.audio_duration_ms = 10; | |
682 | + metrics2.audio_duration_ms = 25; | |
683 | + metrics_sum.audio_duration_ms = 35; | |
684 | + metrics1.media_timer_min_ms = 10; | |
685 | + metrics2.media_timer_min_ms = 25; | |
686 | + metrics_sum.media_timer_min_ms = 10; | |
687 | + metrics1.media_timer_max_ms = 100; | |
688 | + metrics2.media_timer_max_ms = 200; | |
689 | + metrics_sum.media_timer_max_ms = 200; | |
690 | + metrics1.media_timer_avg_ms = 50; | |
691 | + metrics1.total_scheduling_count = 50; | |
692 | + metrics2.media_timer_avg_ms = 100; | |
693 | + metrics2.total_scheduling_count = 50; | |
694 | + metrics_sum.media_timer_avg_ms = 75; | |
695 | + metrics_sum.total_scheduling_count = 100; | |
696 | + metrics1.buffer_overruns_max_count = 70; | |
697 | + metrics2.buffer_overruns_max_count = 80; | |
698 | + metrics_sum.buffer_overruns_max_count = 80; | |
699 | + metrics1.buffer_underruns_average = 80; | |
700 | + metrics1.buffer_underruns_count = 1200; | |
701 | + metrics2.buffer_underruns_average = 130; | |
702 | + metrics2.buffer_underruns_count = 2400; | |
703 | + metrics_sum.buffer_underruns_average = 113.33333333; | |
704 | + metrics_sum.buffer_underruns_count = 3600; | |
705 | + DeviceInfo* info = MakeDeviceInfo( | |
706 | + BTM_COD_MAJOR_AUDIO_TEST, | |
707 | + DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); | |
708 | + A2DPSession* session = MakeA2DPSession(metrics_sum); | |
709 | + bt_sessions_.push_back(MakeBluetoothSession( | |
710 | + 1, | |
711 | + BluetoothSession_ConnectionTechnologyType:: | |
712 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
713 | + BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, | |
714 | + info, nullptr, session)); | |
715 | + UpdateLog(); | |
716 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); | |
717 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); | |
718 | + sleep_ms(1000); | |
719 | + std::string msg_str; | |
720 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
721 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
722 | +} | |
723 | + | |
724 | +/* | |
725 | + * Test Case: A2DPSessionDumpBeforeTwoUpdatesTest | |
726 | + * | |
727 | + * 1. Create Instance | |
728 | + * 2. LogBluetoothSessionStart | |
729 | + * 3. LogBluetoothSessionDeviceInfo | |
730 | + * 5. WriteString | |
731 | + * 6. LogA2dpSession | |
732 | + * 7. LogA2dpSession | |
733 | + * 8. LogBluetoothSessionEnd | |
734 | + * 9. WriteString | |
735 | + * | |
736 | + */ | |
737 | +TEST_F(BluetoothMetricsLoggerTest, A2DPSessionDumpBeforeTwoUpdatesTest) { | |
738 | + /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ | |
739 | + A2dpSessionMetrics metrics1; | |
740 | + A2dpSessionMetrics metrics2; | |
741 | + A2dpSessionMetrics metrics_sum; | |
742 | + metrics1.audio_duration_ms = 10; | |
743 | + metrics2.audio_duration_ms = 25; | |
744 | + metrics_sum.audio_duration_ms = 35; | |
745 | + metrics1.media_timer_min_ms = 10; | |
746 | + metrics2.media_timer_min_ms = 25; | |
747 | + metrics_sum.media_timer_min_ms = 10; | |
748 | + metrics1.media_timer_max_ms = 100; | |
749 | + metrics2.media_timer_max_ms = 200; | |
750 | + metrics_sum.media_timer_max_ms = 200; | |
751 | + metrics1.media_timer_avg_ms = 50; | |
752 | + metrics1.total_scheduling_count = 50; | |
753 | + metrics2.media_timer_avg_ms = 100; | |
754 | + metrics2.total_scheduling_count = 50; | |
755 | + metrics_sum.media_timer_avg_ms = 75; | |
756 | + metrics_sum.total_scheduling_count = 100; | |
757 | + metrics1.buffer_overruns_max_count = 70; | |
758 | + metrics2.buffer_overruns_max_count = 80; | |
759 | + metrics_sum.buffer_overruns_max_count = 80; | |
760 | + metrics1.buffer_underruns_average = 80; | |
761 | + metrics1.buffer_underruns_count = 1200; | |
762 | + metrics2.buffer_underruns_average = 130; | |
763 | + metrics2.buffer_underruns_count = 2400; | |
764 | + metrics_sum.buffer_underruns_average = 113.33333333; | |
765 | + metrics_sum.buffer_underruns_count = 3600; | |
766 | + DeviceInfo* info = MakeDeviceInfo( | |
767 | + BTM_COD_MAJOR_AUDIO_TEST, | |
768 | + DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); | |
769 | + bt_sessions_.push_back(MakeBluetoothSession( | |
770 | + 1, | |
771 | + BluetoothSession_ConnectionTechnologyType:: | |
772 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
773 | + BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, | |
774 | + info, nullptr, nullptr)); | |
775 | + UpdateLog(); | |
776 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( | |
777 | + CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); | |
778 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( | |
779 | + BTM_COD_MAJOR_AUDIO_TEST, DEVICE_TYPE_BREDR); | |
780 | + sleep_ms(1000); | |
781 | + std::string msg_str; | |
782 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
783 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
784 | + ClearLog(); | |
785 | + info = MakeDeviceInfo( | |
786 | + BTM_COD_MAJOR_AUDIO_TEST, | |
787 | + DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); | |
788 | + A2DPSession* session = MakeA2DPSession(metrics_sum); | |
789 | + bt_sessions_.push_back(MakeBluetoothSession( | |
790 | + 1, | |
791 | + BluetoothSession_ConnectionTechnologyType:: | |
792 | + BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, | |
793 | + BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, | |
794 | + info, nullptr, session)); | |
795 | + UpdateLog(); | |
796 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); | |
797 | + BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); | |
798 | + sleep_ms(1000); | |
799 | + BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( | |
800 | + DISCONNECT_REASON_UNKNOWN, 0); | |
801 | + msg_str.clear(); | |
802 | + BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true); | |
803 | + EXPECT_THAT(msg_str, StrEq(bt_log_str_)); | |
804 | +} | |
805 | +} |
@@ -164,7 +164,7 @@ void btm_acl_init (void) | ||
164 | 164 | ** NULL if not found. |
165 | 165 | ** |
166 | 166 | *******************************************************************************/ |
167 | -tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport) | |
167 | +tACL_CONN *btm_bda_to_acl (const BD_ADDR bda, tBT_TRANSPORT transport) | |
168 | 168 | { |
169 | 169 | tACL_CONN *p = &btm_cb.acl_db[0]; |
170 | 170 | UINT16 xx; |
@@ -1002,6 +1002,43 @@ void BTM_SetDefaultLinkPolicy (UINT16 settings) | ||
1002 | 1002 | btsnd_hcic_write_def_policy_set(settings); |
1003 | 1003 | } |
1004 | 1004 | |
1005 | + | |
1006 | +void btm_use_preferred_conn_params(BD_ADDR bda) { | |
1007 | + tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE); | |
1008 | + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda); | |
1009 | + | |
1010 | + /* If there are any preferred connection parameters, set them now */ | |
1011 | + if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) && | |
1012 | + (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) && | |
1013 | + (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) && | |
1014 | + (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) && | |
1015 | + (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) && | |
1016 | + (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) && | |
1017 | + (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) && | |
1018 | + ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int && | |
1019 | + p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) || | |
1020 | + (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) || | |
1021 | + (p_lcb->latency > p_dev_rec->conn_params.slave_latency) || | |
1022 | + (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout))) | |
1023 | + { | |
1024 | + BTM_TRACE_DEBUG ("%s: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", __func__, | |
1025 | + p_lcb->handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int, | |
1026 | + p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout); | |
1027 | + | |
1028 | + p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int; | |
1029 | + p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int; | |
1030 | + p_lcb->timeout = p_dev_rec->conn_params.supervision_tout; | |
1031 | + p_lcb->latency = p_dev_rec->conn_params.slave_latency; | |
1032 | + | |
1033 | + btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, | |
1034 | + p_dev_rec->conn_params.min_conn_int, | |
1035 | + p_dev_rec->conn_params.max_conn_int, | |
1036 | + p_dev_rec->conn_params.slave_latency, | |
1037 | + p_dev_rec->conn_params.supervision_tout, | |
1038 | + 0, 0); | |
1039 | + } | |
1040 | +} | |
1041 | + | |
1005 | 1042 | /******************************************************************************* |
1006 | 1043 | ** |
1007 | 1044 | ** Function btm_read_remote_version_complete |
@@ -1041,8 +1078,9 @@ void btm_read_remote_version_complete (UINT8 *p) | ||
1041 | 1078 | } |
1042 | 1079 | |
1043 | 1080 | #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) |
1044 | - if (p_acl_cb->transport == BT_TRANSPORT_LE){ | |
1081 | + if (p_acl_cb->transport == BT_TRANSPORT_LE) { | |
1045 | 1082 | l2cble_notify_le_connection (p_acl_cb->remote_addr); |
1083 | + btm_use_preferred_conn_params(p_acl_cb->remote_addr); | |
1046 | 1084 | } |
1047 | 1085 | #endif // (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) |
1048 | 1086 | BTM_TRACE_WARNING ("btm_read_remote_version_complete: BDA: %02x-%02x-%02x-%02x-%02x-%02x", |
@@ -1527,7 +1565,7 @@ UINT16 btm_get_acl_disc_reason_code (void) | ||
1527 | 1565 | ** Returns the handle of the connection, or 0xFFFF if none. |
1528 | 1566 | ** |
1529 | 1567 | *******************************************************************************/ |
1530 | -UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport) | |
1568 | +UINT16 BTM_GetHCIConnHandle (const BD_ADDR remote_bda, tBT_TRANSPORT transport) | |
1531 | 1569 | { |
1532 | 1570 | tACL_CONN *p; |
1533 | 1571 | BTM_TRACE_DEBUG ("BTM_GetHCIConnHandle"); |
@@ -71,7 +71,7 @@ extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr); | ||
71 | 71 | ** Returns TRUE if added OK, else FALSE |
72 | 72 | ** |
73 | 73 | *******************************************************************************/ |
74 | -BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE dev_type, | |
74 | +BOOLEAN BTM_SecAddBleDevice (const BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE dev_type, | |
75 | 75 | tBLE_ADDR_TYPE addr_type) |
76 | 76 | { |
77 | 77 | BTM_TRACE_DEBUG ("%s: dev_type=0x%x", __func__, dev_type); |
@@ -485,11 +485,10 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data) | ||
485 | 485 | tSMP_STATUS res_smp = (res == BTM_SUCCESS) ? SMP_SUCCESS : SMP_OOB_FAIL; |
486 | 486 | tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr); |
487 | 487 | |
488 | - BTM_TRACE_DEBUG ("BTM_BleOobDataReply"); | |
488 | + BTM_TRACE_DEBUG ("%s:", __func__); | |
489 | 489 | |
490 | - if (p_dev_rec == NULL) | |
491 | - { | |
492 | - BTM_TRACE_ERROR("BTM_BleOobDataReply() to Unknown device"); | |
490 | + if (p_dev_rec == NULL) { | |
491 | + BTM_TRACE_ERROR("%s: Unknown device", __func__); | |
493 | 492 | return; |
494 | 493 | } |
495 | 494 |
@@ -498,6 +497,47 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data) | ||
498 | 497 | #endif |
499 | 498 | } |
500 | 499 | |
500 | +/******************************************************************************* | |
501 | +** | |
502 | +** Function BTM_BleSecureConnectionOobDataReply | |
503 | +** | |
504 | +** Description This function is called to provide the OOB data for | |
505 | +** SMP in response to BTM_LE_OOB_REQ_EVT when secure connection | |
506 | +** data is available | |
507 | +** | |
508 | +** Parameters: bd_addr - Address of the peer device | |
509 | +** p_c - pointer to Confirmation. | |
510 | +** p_r - pointer to Randomizer | |
511 | +** | |
512 | +*******************************************************************************/ | |
513 | +void BTM_BleSecureConnectionOobDataReply(BD_ADDR bd_addr, | |
514 | + uint8_t *p_c, uint8_t *p_r) | |
515 | +{ | |
516 | +#if SMP_INCLUDED == TRUE | |
517 | + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr); | |
518 | + | |
519 | + BTM_TRACE_DEBUG ("%s:", __func__); | |
520 | + | |
521 | + if (p_dev_rec == NULL) { | |
522 | + BTM_TRACE_ERROR("%s: Unknown device", __func__); | |
523 | + return; | |
524 | + } | |
525 | + | |
526 | + p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED; | |
527 | + | |
528 | + tSMP_SC_OOB_DATA oob; | |
529 | + memset(&oob, 0, sizeof(tSMP_SC_OOB_DATA)); | |
530 | + | |
531 | + oob.peer_oob_data.present = true; | |
532 | + memcpy(&oob.peer_oob_data.randomizer, p_r, BT_OCTET16_LEN); | |
533 | + memcpy(&oob.peer_oob_data.commitment, p_c, BT_OCTET16_LEN); | |
534 | + oob.peer_oob_data.addr_rcvd_from.type = p_dev_rec->ble.ble_addr_type; | |
535 | + memcpy(&oob.peer_oob_data.addr_rcvd_from.bda, bd_addr, sizeof(BD_ADDR)); | |
536 | + | |
537 | + SMP_SecureConnectionOobDataReply((uint8_t*)&oob); | |
538 | +#endif | |
539 | +} | |
540 | + | |
501 | 541 | /****************************************************************************** |
502 | 542 | ** |
503 | 543 | ** Function BTM_BleSetConnScanParams |
@@ -422,12 +422,12 @@ bool is_address_equal(void *data, void *context) | ||
422 | 422 | ** Returns Pointer to the record or NULL |
423 | 423 | ** |
424 | 424 | *******************************************************************************/ |
425 | -tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr) | |
425 | +tBTM_SEC_DEV_REC *btm_find_dev(const BD_ADDR bd_addr) | |
426 | 426 | { |
427 | 427 | if (!bd_addr) |
428 | 428 | return NULL; |
429 | 429 | |
430 | - list_node_t *n = list_foreach(btm_cb.sec_dev_rec, is_address_equal, bd_addr); | |
430 | + list_node_t *n = list_foreach(btm_cb.sec_dev_rec, is_address_equal, (void*)bd_addr); | |
431 | 431 | if (n) |
432 | 432 | return list_node(n); |
433 | 433 |
@@ -1131,7 +1131,7 @@ tBTM_STATUS BTM_CancelRemoteDeviceName (void) | ||
1131 | 1131 | ** Returns pointer to entry, or NULL if not found |
1132 | 1132 | ** |
1133 | 1133 | *******************************************************************************/ |
1134 | -tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda) | |
1134 | +tBTM_INQ_INFO *BTM_InqDbRead (const BD_ADDR p_bda) | |
1135 | 1135 | { |
1136 | 1136 | BTM_TRACE_API ("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]", |
1137 | 1137 | p_bda[0], p_bda[1], p_bda[2], p_bda[3], p_bda[4], p_bda[5]); |
@@ -1538,7 +1538,7 @@ BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda) | ||
1538 | 1538 | ** Returns pointer to entry, or NULL if not found |
1539 | 1539 | ** |
1540 | 1540 | *******************************************************************************/ |
1541 | -tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda) | |
1541 | +tINQ_DB_ENT *btm_inq_db_find (const BD_ADDR p_bda) | |
1542 | 1542 | { |
1543 | 1543 | UINT16 xx; |
1544 | 1544 | tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db; |
@@ -952,7 +952,7 @@ extern void btm_process_cancel_complete(UINT8 status, UINT8 mode); | ||
952 | 952 | extern void btm_event_filter_complete (UINT8 *p); |
953 | 953 | extern void btm_inq_stop_on_ssp(void); |
954 | 954 | extern void btm_inq_clear_ssp(void); |
955 | -extern tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda); | |
955 | +extern tINQ_DB_ENT *btm_inq_db_find (const BD_ADDR p_bda); | |
956 | 956 | extern BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda); |
957 | 957 | |
958 | 958 | extern BOOLEAN btm_lookup_eir(BD_ADDR_PTR p_rem_addr); |
@@ -999,7 +999,7 @@ extern void btm_establish_continue (tACL_CONN *p_acl_cb); | ||
999 | 999 | extern void btm_acl_chk_peer_pkt_type_support (tACL_CONN *p, UINT16 *p_pkt_type); |
1000 | 1000 | /* Read maximum data packet that can be sent over current connection */ |
1001 | 1001 | extern UINT16 btm_get_max_packet_size (BD_ADDR addr); |
1002 | -extern tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport); | |
1002 | +extern tACL_CONN *btm_bda_to_acl (const BD_ADDR bda, tBT_TRANSPORT transport); | |
1003 | 1003 | extern BOOLEAN btm_acl_notif_conn_collision (BD_ADDR bda); |
1004 | 1004 | |
1005 | 1005 | extern void btm_pm_reset(void); |
@@ -1080,7 +1080,7 @@ extern BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr); | ||
1080 | 1080 | extern tBTM_SEC_DEV_REC *btm_sec_allocate_dev_rec(void); |
1081 | 1081 | extern tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr); |
1082 | 1082 | extern void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec); |
1083 | -extern tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr); | |
1083 | +extern tBTM_SEC_DEV_REC *btm_find_dev (const BD_ADDR bd_addr); | |
1084 | 1084 | extern tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr); |
1085 | 1085 | extern tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle); |
1086 | 1086 | extern tBTM_BOND_TYPE btm_get_bond_type_dev(BD_ADDR bd_addr); |
@@ -2555,7 +2555,7 @@ extern UINT8 *BTM_ReadAllRemoteFeatures (BD_ADDR addr); | ||
2555 | 2555 | ** Returns pointer to entry, or NULL if not found |
2556 | 2556 | ** |
2557 | 2557 | *******************************************************************************/ |
2558 | -extern tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda); | |
2558 | +extern tBTM_INQ_INFO *BTM_InqDbRead (const BD_ADDR p_bda); | |
2559 | 2559 | |
2560 | 2560 | |
2561 | 2561 | /******************************************************************************* |
@@ -3761,7 +3761,7 @@ extern tBTM_STATUS BTM_SetSsrParams (BD_ADDR remote_bda, UINT16 max_lat, | ||
3761 | 3761 | ** Returns the handle of the connection, or 0xFFFF if none. |
3762 | 3762 | ** |
3763 | 3763 | *******************************************************************************/ |
3764 | -extern UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport); | |
3764 | +extern UINT16 BTM_GetHCIConnHandle (const BD_ADDR remote_bda, tBT_TRANSPORT transport); | |
3765 | 3765 | |
3766 | 3766 | /******************************************************************************* |
3767 | 3767 | ** |
@@ -917,7 +917,7 @@ extern "C" { | ||
917 | 917 | ** Returns TRUE if added OK, else FALSE |
918 | 918 | ** |
919 | 919 | *******************************************************************************/ |
920 | -extern BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, | |
920 | +extern BOOLEAN BTM_SecAddBleDevice (const BD_ADDR bd_addr, BD_NAME bd_name, | |
921 | 921 | tBT_DEVICE_TYPE dev_type, tBLE_ADDR_TYPE addr_type); |
922 | 922 | |
923 | 923 | /******************************************************************************* |
@@ -1241,6 +1241,22 @@ extern void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res); | ||
1241 | 1241 | *******************************************************************************/ |
1242 | 1242 | extern void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data); |
1243 | 1243 | |
1244 | +/******************************************************************************* | |
1245 | +** | |
1246 | +** Function BTM_BleSecureConnectionOobDataReply | |
1247 | +** | |
1248 | +** Description This function is called to provide the OOB data for | |
1249 | +** SMP in response to BTM_LE_OOB_REQ_EVT when secure connection | |
1250 | +** data is available | |
1251 | +** | |
1252 | +** Parameters: bd_addr - Address of the peer device | |
1253 | +** p_c - pointer to Confirmation | |
1254 | +** p_r - pointer to Randomizer. | |
1255 | +** | |
1256 | +*******************************************************************************/ | |
1257 | +extern void BTM_BleSecureConnectionOobDataReply(BD_ADDR bd_addr, | |
1258 | + uint8_t *p_c, uint8_t *p_r); | |
1259 | + | |
1244 | 1260 | |
1245 | 1261 | /******************************************************************************* |
1246 | 1262 | ** |
@@ -33,6 +33,7 @@ | ||
33 | 33 | #include "device/include/controller.h" |
34 | 34 | #include "device/include/interop.h" |
35 | 35 | #include "stack_config.h" |
36 | +#include "btif_debug_l2c.h" | |
36 | 37 | |
37 | 38 | #if (BLE_INCLUDED == TRUE) |
38 | 39 |
@@ -234,42 +235,6 @@ UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport) | ||
234 | 235 | return reason; |
235 | 236 | } |
236 | 237 | |
237 | -void l2cble_use_preferred_conn_params(BD_ADDR bda) { | |
238 | - tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE); | |
239 | - tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda); | |
240 | - | |
241 | - /* If there are any preferred connection parameters, set them now */ | |
242 | - if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) && | |
243 | - (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) && | |
244 | - (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) && | |
245 | - (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) && | |
246 | - (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) && | |
247 | - (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) && | |
248 | - (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) && | |
249 | - ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int && | |
250 | - p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) || | |
251 | - (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) || | |
252 | - (p_lcb->latency > p_dev_rec->conn_params.slave_latency) || | |
253 | - (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout))) | |
254 | - { | |
255 | - L2CAP_TRACE_DEBUG ("%s: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", __func__, | |
256 | - p_lcb->handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int, | |
257 | - p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout); | |
258 | - | |
259 | - p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int; | |
260 | - p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int; | |
261 | - p_lcb->timeout = p_dev_rec->conn_params.supervision_tout; | |
262 | - p_lcb->latency = p_dev_rec->conn_params.slave_latency; | |
263 | - | |
264 | - btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, | |
265 | - p_dev_rec->conn_params.min_conn_int, | |
266 | - p_dev_rec->conn_params.max_conn_int, | |
267 | - p_dev_rec->conn_params.slave_latency, | |
268 | - p_dev_rec->conn_params.supervision_tout, | |
269 | - 0, 0); | |
270 | - } | |
271 | -} | |
272 | - | |
273 | 238 | /******************************************************************************* |
274 | 239 | ** |
275 | 240 | ** Function l2cble_notify_le_connection |
@@ -308,7 +273,7 @@ void l2cble_notify_le_connection (BD_ADDR bda) | ||
308 | 273 | if (!BTM_GetRemoteDeviceName(bda, bdname) || !*bdname || |
309 | 274 | (!interop_match_name(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS, (const char*) bdname))) |
310 | 275 | { |
311 | - l2cble_use_preferred_conn_params(bda); | |
276 | + //l2cble_use_preferred_conn_params(bda); | |
312 | 277 | } |
313 | 278 | } |
314 | 279 |
@@ -578,6 +543,14 @@ static void l2cble_start_conn_update (tL2C_LCB *p_lcb) | ||
578 | 543 | p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM; |
579 | 544 | } |
580 | 545 | } |
546 | + | |
547 | + /* Record the BLE connection update request. */ | |
548 | + if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) { | |
549 | + bt_bdaddr_t bd_addr; | |
550 | + bdcpy(bd_addr.address, p_lcb->remote_bd_addr); | |
551 | + btif_debug_ble_connection_update_request(bd_addr, min_conn_int, max_conn_int, slave_latency, | |
552 | + supervision_tout); | |
553 | + } | |
581 | 554 | } |
582 | 555 | |
583 | 556 | /******************************************************************************* |
@@ -612,6 +585,12 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, | ||
612 | 585 | |
613 | 586 | l2cble_start_conn_update(p_lcb); |
614 | 587 | |
588 | + /* Record the BLE connection update response. */ | |
589 | + bt_bdaddr_t bd_addr; | |
590 | + bdcpy(bd_addr.address, p_lcb->remote_bd_addr); | |
591 | + btif_debug_ble_connection_update_response(bd_addr, status, interval, | |
592 | + latency, timeout); | |
593 | + | |
615 | 594 | L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__, p_lcb->conn_update_mask); |
616 | 595 | } |
617 | 596 |
@@ -384,10 +384,11 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset) | ||
384 | 384 | SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len); |
385 | 385 | cpy_len = rem_len; |
386 | 386 | } |
387 | -#if (SDP_DEBUG_RAW == TRUE) | |
388 | - SDP_TRACE_WARNING("list_len :%d cpy_len:%d raw_size:%d raw_used:%d", | |
389 | - list_len, cpy_len, p_ccb->p_db->raw_size, p_ccb->p_db->raw_used); | |
390 | -#endif | |
387 | + SDP_TRACE_WARNING( | |
388 | + "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d " | |
389 | + "raw_used:%d raw_data:%p", | |
390 | + __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db, | |
391 | + p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data); | |
391 | 392 | memcpy (&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len); |
392 | 393 | p_ccb->p_db->raw_used += cpy_len; |
393 | 394 | } |