OSDN Git Service

[automerger] DO NOT MERGE: btif: require pairing dialog for JustWorks SSP am: dff6cd8...
authorAndroid Build Merger (Role) <noreply-android-build-merger@google.com>
Thu, 30 May 2019 16:55:59 +0000 (16:55 +0000)
committerAndroid Build Merger (Role) <noreply-android-build-merger@google.com>
Thu, 30 May 2019 16:55:59 +0000 (16:55 +0000)
Change-Id: I8d3abdacbf67c5f8cbd1cf3b1fb63528b4a95811

56 files changed:
EventLogTags.logtags
bta/ag/bta_ag_api.c
bta/ag/bta_ag_cmd.c
bta/ag/bta_ag_int.h
bta/ag/bta_ag_main.c
bta/ag/bta_ag_sco.c
bta/dm/bta_dm_act.c
bta/dm/bta_dm_api.c
bta/dm/bta_dm_int.h
bta/gatt/bta_gattc_cache.c
bta/gatt/bta_gattc_utils.c
bta/hf_client/bta_hf_client_sco.c
bta/hh/bta_hh_le.c
bta/include/bta_ag_api.h
bta/include/bta_api.h
bta/include/bta_gatt_api.h
btif/src/bluetooth.c
btif/src/btif_core.c
btif/src/btif_dm.c
btif/src/btif_gatt_client.c
btif/src/btif_hf.c
btif/src/btif_media_task.c
btif/src/btif_storage.c
conf/bt_stack.conf
device/include/interop.h
device/include/interop_database.h
device/src/interop.c
hci/src/btsnoop.c
include/bt_target.h
main/stack_config.c
osi/Android.mk
osi/BUILD.gn
osi/include/leaky_bonded_queue.h [new file with mode: 0644]
osi/include/metrics.h
osi/include/metrics_cpp.h [new file with mode: 0644]
osi/src/metrics.cpp
osi/src/metrics_linux.cpp
osi/src/protos/bluetooth.proto
osi/src/wakelock.c
osi/test/leaky_bonded_queue_test.cpp [new file with mode: 0644]
osi/test/metrics_test.cpp [new file with mode: 0644]
stack/avdt/avdt_l2c.c
stack/btm/btm_acl.c
stack/btm/btm_ble.c
stack/btm/btm_dev.c
stack/btm/btm_inq.c
stack/btm/btm_int.h
stack/gatt/gatt_main.c
stack/include/btm_api.h
stack/include/btm_ble_api.h
stack/include/l2c_api.h
stack/l2cap/l2c_ble.c
stack/l2cap/l2c_int.h
stack/l2cap/l2c_link.c
stack/l2cap/l2c_utils.c
stack/sdp/sdp_discovery.c

index 79f49e7..dc1d239 100644 (file)
@@ -36,4 +36,3 @@
 1010000 bt_hci_timeout (opcode|1)
 1010001 bt_config_source (opcode|1)
 1010002 bt_hci_unknown_type (hci_type|1)
-1010003 bt_conn_param_update_status (status|1)
index 872e71d..f3415be 100644 (file)
@@ -287,14 +287,3 @@ void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec)
 
     bta_sys_sendmsg(p_buf);
 }
-
-void BTA_AgSetScoAllowed(bool value)
-{
-    tBTA_AG_API_SET_SCO_ALLOWED *p_buf =
-        (tBTA_AG_API_SET_SCO_ALLOWED *)osi_malloc(sizeof(tBTA_AG_API_SET_SCO_ALLOWED));
-
-    p_buf->hdr.event = BTA_AG_API_SET_SCO_ALLOWED_EVT;
-    p_buf->value = value;
-
-    bta_sys_sendmsg(p_buf);
-}
index 1a92a86..7a882ec 100644 (file)
@@ -1200,7 +1200,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
                 p_scb->peer_features, features);
 
             /* send BRSF, send OK */
-            bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, NULL, (int16_t)features);
+            bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, NULL, (int16_t) features);
             bta_ag_send_ok(p_scb);
             break;
         }
index 01005ee..eac98c2 100644 (file)
@@ -101,8 +101,7 @@ enum
 
     /* these events are handled outside of the state machine */
     BTA_AG_API_ENABLE_EVT,
-    BTA_AG_API_DISABLE_EVT,
-    BTA_AG_API_SET_SCO_ALLOWED_EVT
+    BTA_AG_API_DISABLE_EVT
 };
 
 /* Actions to perform after a SCO event */
@@ -182,13 +181,6 @@ typedef struct
     tBTA_AG_PEER_CODEC  codec;
 } tBTA_AG_API_SETCODEC;
 
-/* data type for BTA_AG_API_SET_SCO_ALLOWED_EVT */
-typedef struct
-{
-    BT_HDR              hdr;
-    bool                value;
-} tBTA_AG_API_SET_SCO_ALLOWED;
-
 /* data type for BTA_AG_DISC_RESULT_EVT */
 typedef struct
 {
@@ -431,5 +423,4 @@ extern void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
 extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param);
 extern void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
 extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
-extern void bta_ag_set_sco_allowed(tBTA_AG_DATA *p_data);
 #endif /* BTA_AG_INT_H */
index d6cc556..3abd1ef 100644 (file)
@@ -906,10 +906,6 @@ BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg)
             bta_ag_api_result((tBTA_AG_DATA *) p_msg);
             break;
 
-        case BTA_AG_API_SET_SCO_ALLOWED_EVT:
-            bta_ag_set_sco_allowed((tBTA_AG_DATA *) p_msg);
-            break;
-
         /* all others reference scb by handle */
         default:
             if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
index 3399e69..89e6f6c 100644 (file)
@@ -50,8 +50,6 @@ static char *bta_ag_sco_evt_str(UINT8 event);
 static char *bta_ag_sco_state_str(UINT8 state);
 #endif
 
-static bool sco_allowed = true;
-
 #define BTA_AG_NO_EDR_ESCO  (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
                              BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
                              BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
@@ -1350,12 +1348,6 @@ void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
     UINT8 event;
     UNUSED(p_data);
 
-    if (!sco_allowed)
-    {
-        APPL_TRACE_DEBUG("%s not opening sco, by policy", __func__);
-        return;
-    }
-
     /* if another scb using sco, this is a transfer */
     if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
     {
@@ -1680,12 +1672,6 @@ void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param)
     }
 }
 
-void bta_ag_set_sco_allowed(tBTA_AG_DATA *p_data)
-{
-    sco_allowed = ((tBTA_AG_API_SET_SCO_ALLOWED *) p_data)->value;
-    APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
-}
-
 /*******************************************************************************
 **  Debugging functions
 *******************************************************************************/
index 12caa12..e361970 100644 (file)
@@ -2881,6 +2881,8 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
     /*case BTM_SP_KEY_REQ_EVT: */
     case BTM_SP_KEY_NOTIF_EVT:
 #endif
+        bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
+
         if(BTM_SP_CFM_REQ_EVT == event)
         {
           /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
@@ -2906,7 +2908,6 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
            }
         }
 
-        bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
         if (BTM_SP_KEY_NOTIF_EVT == event)
         {
             /* If the device name is not known, save bdaddr and devclass
@@ -4397,6 +4398,11 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
             bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event);
             break;
 
+        case BTM_LE_SC_OOB_REQ_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_SC_OOB_REQ_EVT, &sec_event);
+            break;
+
         case BTM_LE_KEY_EVT:
             bdcpy(sec_event.ble_key.bd_addr, bda);
             sec_event.ble_key.key_type = p_data->key.key_type;
@@ -4666,11 +4672,10 @@ void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data)
 void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data)
 {
     if (!L2CA_UpdateBleConnParams(p_data->ble_update_conn_params.bd_addr,
-                                  p_data->ble_update_conn_params.min_int,
-                                  p_data->ble_update_conn_params.max_int,
-                                  p_data->ble_update_conn_params.latency,
-                                  p_data->ble_update_conn_params.timeout,
-                                  p_data->ble_update_conn_params.p_conn_param_update_cback))
+                                 p_data->ble_update_conn_params.min_int,
+                                 p_data->ble_update_conn_params.max_int,
+                                 p_data->ble_update_conn_params.latency,
+                                 p_data->ble_update_conn_params.timeout))
     {
         APPL_TRACE_ERROR("Update connection parameters failed!");
     }
index 323e58e..82dd8b2 100644 (file)
@@ -1311,6 +1311,39 @@ void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services, t
     UNUSED(p_cback);
 #endif
 }
+/*******************************************************************************
+**
+** Function         BTA_DmBleUpdateConnectionParam
+**
+** Description      Update connection parameters, can only be used when connection is up.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  min_int   -     minimum connection interval, [0x0004~ 0x4000]
+**                  max_int   -     maximum connection interval, [0x0004~ 0x4000]
+**                  latency   -     slave latency [0 ~ 500]
+**                  timeout   -     supervision timeout [0x000a ~ 0xc80]
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleUpdateConnectionParam(BD_ADDR bd_addr, UINT16 min_int,
+                                    UINT16 max_int, UINT16 latency,
+                                    UINT16 timeout)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_UPDATE_CONN_PARAM *p_msg =
+        (tBTA_DM_API_UPDATE_CONN_PARAM *)osi_calloc(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
+
+    p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
+    bdcpy(p_msg->bd_addr, bd_addr);
+    p_msg->min_int = min_int;
+    p_msg->max_int = max_int;
+    p_msg->latency = latency;
+    p_msg->timeout = timeout;
+
+    bta_sys_sendmsg(p_msg);
+#endif
+}
 
 /*******************************************************************************
 **
@@ -1713,19 +1746,17 @@ void BTA_DmEnableScanFilter(UINT8 action, tBTA_DM_BLE_PF_STATUS_CBACK *p_cmpl_cb
 **
 ** Description      Update connection parameters, can only be used when connection is up.
 **
-** Parameters:      bd_addr   -     BD address of the peer
+** Parameters:      bd_addr   - BD address of the peer
 **                  min_int   -     minimum connection interval, [0x0004~ 0x4000]
 **                  max_int   -     maximum connection interval, [0x0004~ 0x4000]
 **                  latency   -     slave latency [0 ~ 500]
 **                  timeout   -     supervision timeout [0x000a ~ 0xc80]
-                    p_cback   -     callback on connection parameters updated
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
-                                     UINT16 max_int, UINT16 latency, UINT16 timeout,
-                                     tBTA_DM_BLE_CONN_PARAM_CBACK *p_cback)
+void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
+                                    UINT16 latency, UINT16 timeout)
 {
     tBTA_DM_API_UPDATE_CONN_PARAM *p_msg =
         (tBTA_DM_API_UPDATE_CONN_PARAM *)osi_calloc(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
@@ -1736,7 +1767,6 @@ void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
     p_msg->max_int = max_int;
     p_msg->latency = latency;
     p_msg->timeout = timeout;
-    p_msg->p_conn_param_update_cback = p_cback;
 
     bta_sys_sendmsg(p_msg);
 }
index 796d4a5..a5fe0ad 100644 (file)
@@ -436,6 +436,7 @@ typedef struct
     UINT16                  conn_int_max;
     UINT16                  supervision_tout;
     UINT16                  slave_latency;
+
 }tBTA_DM_API_BLE_CONN_PARAMS;
 
 typedef struct
@@ -610,8 +611,6 @@ typedef struct
     tBTA_DM_LINK_TYPE link_type;
 
 } tBTA_DM_API_REMOVE_ALL_ACL;
-
-/* data type for BTA_DM_API_UPDATE_CONN_PARAM_EVT */
 typedef struct
 {
     BT_HDR      hdr;
@@ -620,8 +619,7 @@ typedef struct
     UINT16      max_int;
     UINT16      latency;
     UINT16      timeout;
-    tBTA_DM_BLE_CONN_PARAM_CBACK *p_conn_param_update_cback;
-} tBTA_DM_API_UPDATE_CONN_PARAM;
+}tBTA_DM_API_UPDATE_CONN_PARAM;
 
 #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
 typedef struct
index 62b4d81..45d2588 100644 (file)
@@ -314,7 +314,8 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
         descriptor->handle = handle;
         memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID));
 
-        if (service->characteristics == NULL) {
+        if (service->characteristics == NULL ||
+            list_is_empty(service->characteristics)) {
             APPL_TRACE_ERROR("%s: Illegal action to add descriptor before adding a characteristic!",
                              __func__);
             osi_free(descriptor);
@@ -1517,12 +1518,6 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
 *******************************************************************************/
 bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb)
 {
-
-#if (defined WEAR_DISABLE_GATT_CACHE && WEAR_DISABLE_GATT_CACHE == TRUE)
-    LOG_WARN(LOG_TAG, "%s GATT cache not used.", __func__);
-    return false;
-#endif
-
     char fname[255] = {0};
     bta_gattc_generate_cache_file_name(fname, p_clcb->p_srcb->server_bda);
 
index bd0d466..8910bd3 100644 (file)
@@ -302,6 +302,12 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
             p_srcb->connected = FALSE;
             p_srcb->state = BTA_GATTC_SERV_IDLE;
             p_srcb->mtu = 0;
+
+            /* clean up cache */
+            if (p_srcb->p_srvc_cache) {
+                list_free(p_srcb->p_srvc_cache);
+                p_srcb->p_srvc_cache = NULL;
+            }
         }
 
         osi_free_and_reset((void **)&p_clcb->p_q_cmd);
index 1be82a5..129dc9e 100644 (file)
@@ -231,7 +231,7 @@ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
     /* no match found; disconnect sco, init sco variables */
     else
     {
-        /* should not force the sco state to shutdown state here */
+        bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
         BTM_RemoveSco(sco_idx);
     }
 }
index a21df35..75d6bd3 100644 (file)
@@ -1804,8 +1804,8 @@ void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
         if (tout < BTM_BLE_CONN_TIMEOUT_MIN_DEF)
             tout = BTM_BLE_CONN_TIMEOUT_MIN_DEF;
 
-        BTM_BleSetPrefConnParams(p_dev_cb->addr, min, max, latency, tout);
-        L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout, NULL);
+        BTM_BleSetPrefConnParams (p_dev_cb->addr, min, max, latency, tout);
+        L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
     }
     else
     {
@@ -2155,12 +2155,19 @@ void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
 
     if (p_dev_cb == NULL)
     {
-        APPL_TRACE_ERROR("notification received from Unknown device");
+        APPL_TRACE_ERROR("%s: notification received from Unknown device, conn_id: 0x%04x",
+            __func__, p_data->conn_id);
         return;
     }
 
     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
                                                                           p_data->handle);
+    if (p_char == NULL)
+    {
+        APPL_TRACE_ERROR("%s: notification received for Unknown Characteristic, conn_id: 0x%04x, handle: 0x%04x",
+            __func__, p_dev_cb->conn_id, p_data->handle);
+        return;
+    }
 
     app_id= p_dev_cb->app_id;
 
@@ -2170,7 +2177,8 @@ void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
                                         p_char->handle);
     if (p_rpt == NULL)
     {
-        APPL_TRACE_ERROR("notification received for Unknown Report");
+        APPL_TRACE_ERROR("%s: notification received for Unknown Report, uuid: 0x%04x, handle: 0x%04x",
+            __func__, p_char->uuid.uu.uuid16, p_char->handle);
         return;
     }
 
index 899461a..e281fb1 100644 (file)
@@ -580,8 +580,6 @@ void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data);
 *******************************************************************************/
 void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec);
 
-void BTA_AgSetScoAllowed(bool value);
-
 #ifdef __cplusplus
 }
 #endif
index 8fdd6ec..4a8cd5f 100644 (file)
@@ -593,7 +593,8 @@ typedef UINT8 tBTA_SIG_STRENGTH_MASK;
 #define BTA_DM_HW_ERROR_EVT             26      /* BT Chip H/W error */
 #define BTA_DM_LE_FEATURES_READ         27      /* Cotroller specific LE features are read */
 #define BTA_DM_ENER_INFO_READ           28      /* Energy info read */
-typedef UINT8 tBTA_DM_SEC_EVT;
+#define BTA_DM_BLE_SC_OOB_REQ_EVT       29      /* SMP SC OOB request event */
+typedef uint8_t tBTA_DM_SEC_EVT;
 
 /* Structure associated with BTA_DM_ENABLE_EVT */
 typedef struct
@@ -933,9 +934,6 @@ typedef void (tBTA_DM_BLE_PF_PARAM_CBACK) (UINT8 action_type, tBTA_DM_BLE_PF_AVB
 typedef void (tBTA_DM_BLE_PF_STATUS_CBACK) (UINT8 action, tBTA_STATUS status,
                                             tBTA_DM_BLE_REF_VALUE ref_value);
 
-/* Connection update callback */
-typedef void (tBTA_DM_BLE_CONN_PARAM_CBACK) (BD_ADDR bd_addr, UINT16 interval, UINT16 latency,
-                                             UINT16 timeout, tBTA_STATUS status);
 
 #define BTA_DM_BLE_PF_BRDCAST_ADDR_FILT  1
 #define BTA_DM_BLE_PF_SERV_DATA_CHG_FILT 2
@@ -2113,7 +2111,7 @@ extern void BTA_BleDisableAdvInstance(UINT8 inst_id);
 **
 ** Description      Update connection parameters, can only be used when connection is up.
 **
-** Parameters:      bd_addr   -     BD address of the peer
+** Parameters:      bd_addr   - BD address of the peer
 **                  min_int   -     minimum connection interval, [0x0004~ 0x4000]
 **                  max_int   -     maximum connection interval, [0x0004~ 0x4000]
 **                  latency   -     slave latency [0 ~ 500]
@@ -2122,9 +2120,8 @@ extern void BTA_BleDisableAdvInstance(UINT8 inst_id);
 ** Returns          void
 **
 *******************************************************************************/
-extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
-                                            UINT16 latency, UINT16 timeout,
-                                            tBTA_DM_BLE_CONN_PARAM_CBACK p_cback);
+extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
+                                   UINT16 max_int, UINT16 latency, UINT16 timeout);
 
 /*******************************************************************************
 **
index 0d0a1fc..4c9f76c 100644 (file)
@@ -146,7 +146,6 @@ typedef UINT8 tBTA_GATT_STATUS;
 #define BTA_GATTC_SCAN_FLT_PARAM_EVT 32 /* Param filter event */
 #define BTA_GATTC_SCAN_FLT_STATUS_EVT 33 /* Filter status event */
 #define BTA_GATTC_ADV_VSC_EVT         34 /* ADV VSC event */
-#define BTA_GATTC_CONN_PARAM_UPD_EVT 35 /* Connection parameter update event */
 
 typedef UINT8 tBTA_GATTC_EVT;
 
index 6be1d19..81964db 100644 (file)
@@ -340,14 +340,8 @@ static int read_energy_info()
 static void dump(int fd, const char **arguments)
 {
     if (arguments != NULL && arguments[0] != NULL) {
-      if (strncmp(arguments[0], "--proto-text", 12) == 0) {
-        btif_update_a2dp_metrics();
-        metrics_print(fd, true);
-        return;
-      }
       if (strncmp(arguments[0], "--proto-bin", 11) == 0) {
-        btif_update_a2dp_metrics();
-        metrics_write(fd, true);
+        metrics_write_base64(fd, true);
         return;
       }
     }
index 7dc93c4..c74c6dd 100644 (file)
@@ -709,18 +709,13 @@ static bt_status_t btif_in_get_adapter_properties(void)
     uint32_t disc_timeout;
     bt_bdaddr_t bonded_devices[BTM_SEC_MAX_DEVICE_RECORDS];
     bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
-    bt_status_t status;
     num_props = 0;
 
     /* BD_ADDR */
     BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDADDR,
                                sizeof(addr), &addr);
-    status = btif_storage_get_adapter_property(&properties[num_props]);
-    // Add BT_PROPERTY_BDADDR property into list only when successful.
-    // Otherwise, skip this property entry.
-    if (status == BT_STATUS_SUCCESS) {
-        num_props++;
-    }
+    btif_storage_get_adapter_property(&properties[num_props]);
+    num_props++;
 
     /* BD_NAME */
     BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDNAME,
index f0d83cd..82745fd 100644 (file)
@@ -233,6 +233,7 @@ static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl);
 static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req);
 static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) ;
 static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type);
+static void btif_dm_ble_sc_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type);
 #endif
 
 static void bte_scan_filt_param_cfg_evt(UINT8 action_type,
@@ -716,7 +717,15 @@ static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transpor
         }
         if (btif_storage_get_remote_addr_type(bd_addr, &addr_type) != BT_STATUS_SUCCESS)
         {
-            btif_storage_set_remote_addr_type(bd_addr, BLE_ADDR_PUBLIC);
+
+            // Try to read address type. OOB pairing might have set it earlier, but
+            // didn't store it, it defaults to BLE_ADDR_PUBLIC
+            uint8_t tmp_dev_type;
+            uint8_t tmp_addr_type;
+            BTM_ReadDevInfo(bd_addr->address, &tmp_dev_type, &tmp_addr_type);
+            addr_type = tmp_addr_type;
+
+            btif_storage_set_remote_addr_type(bd_addr, addr_type);
         }
     }
     if((btif_config_get_int((char const *)&bdstr,"DevType", &device_type) &&
@@ -1654,7 +1663,7 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
     uint32_t i;
     bt_bdaddr_t bd_addr;
 
-    BTIF_TRACE_EVENT("btif_dm_upstreams_cback  ev: %s", dump_dm_event(event));
+    BTIF_TRACE_EVENT("%s: ev: %s", __func__, dump_dm_event(event));
 
     switch (event)
     {
@@ -1893,6 +1902,10 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
             BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. ");
             btif_dm_ble_oob_req_evt(&p_data->rmt_oob);
             break;
+        case BTA_DM_BLE_SC_OOB_REQ_EVT:
+            BTIF_TRACE_DEBUG("BTA_DM_BLE_SC_OOB_REQ_EVT. ");
+            btif_dm_ble_sc_oob_req_evt(&p_data->rmt_oob);
+            break;
         case BTA_DM_BLE_LOCAL_IR_EVT:
             BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. ");
             ble_local_key_cb.is_id_keys_rcvd = TRUE;
@@ -2357,6 +2370,19 @@ bt_status_t btif_dm_create_bond_out_of_band(const bt_bdaddr_t *bd_addr, int tran
     bdcpy(oob_cb.bdaddr, bd_addr->address);
     memcpy(&oob_cb.oob_data, oob_data, sizeof(bt_out_of_band_data_t));
 
+    uint8_t empty[] = {0, 0, 0, 0, 0, 0, 0};
+    // If LE Bluetooth Device Address is provided, use provided address type
+    // value.
+    if (memcmp(oob_data->le_bt_dev_addr, empty, 7) != 0) {
+        /* byte no 7 is address type in LE Bluetooth Address OOB data */
+        uint8_t address_type = oob_data->le_bt_dev_addr[6];
+        if (address_type == BLE_ADDR_PUBLIC || address_type == BLE_ADDR_RANDOM) {
+            // bd_addr->address is already reversed, so use it instead of
+            // oob_data->le_bt_dev_addr
+            BTM_SecAddBleDevice(bd_addr->address, NULL, BT_DEVICE_TYPE_BLE, address_type);
+        }
+    }
+
     bdstr_t bdstr;
     BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport);
     return btif_dm_create_bond(bd_addr, transport);
@@ -2788,29 +2814,36 @@ void btif_dm_set_oob_for_le_io_req(BD_ADDR bd_addr, tBTA_OOB_DATA  *p_has_oob_da
                                    tBTA_LE_AUTH_REQ *p_auth_req)
 {
 
-    /* We currently support only Security Manager TK as OOB data for LE transport.
-       If it's not present mark no OOB data.
-     */
-    if (!is_empty_128bit(oob_cb.oob_data.sm_tk))
-    {
+    if (!is_empty_128bit(oob_cb.oob_data.le_sc_c) &&
+        !is_empty_128bit(oob_cb.oob_data.le_sc_r)) {
+        /* We have LE SC OOB data */
+
+        /* make sure OOB data is for this particular device */
+        if (memcmp(bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) == 0) {
+            *p_auth_req = ((*p_auth_req) | BTM_LE_AUTH_REQ_SC_ONLY);
+            *p_has_oob_data = true;
+        } else {
+            *p_has_oob_data = false;
+            BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address",
+                               __func__);
+        }
+    } else if (!is_empty_128bit(oob_cb.oob_data.sm_tk)) {
+        /* We have security manager TK */
+
         /* make sure OOB data is for this particular device */
         if (memcmp(bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) == 0) {
             // When using OOB with TK, SC Secure Connections bit must be disabled.
             tBTA_LE_AUTH_REQ mask = ~BTM_LE_AUTH_REQ_SC_ONLY;
             *p_auth_req = ((*p_auth_req) & mask);
 
-            *p_has_oob_data = TRUE;
-        }
-        else
-        {
-            *p_has_oob_data = FALSE;
+            *p_has_oob_data = true;
+        } else {
+            *p_has_oob_data = false;
             BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address",
                                __func__);
         }
-    }
-    else
-    {
-        *p_has_oob_data = FALSE;
+    } else {
+        *p_has_oob_data = false;
     }
     BTIF_TRACE_DEBUG("%s *p_has_oob_data=%d", __func__, *p_has_oob_data);
 }
@@ -3053,18 +3086,6 @@ static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
             btif_storage_remove_bonded_device(&bdaddr);
             state = BT_BOND_STATE_NONE;
         } else {
-            /*
-             * Note: This is a Wear-specific feature for iOS pairing.
-             * Store the address of the first bonded device that is also of type LE to
-             * enable auto connection parameter update.
-             */
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-            if (btif_storage_get_num_bonded_devices() == 0) {
-                bdstr_t bdstr;
-                bdaddr_to_string(&bdaddr, bdstr, sizeof(bdstr));
-                btif_config_set_str("Adapter", "AutoConnParamUpdateAddr", bdstr);
-            }
-#endif
             btif_dm_save_ble_bonding_keys();
             BTA_GATTC_Refresh(bd_addr.address);
             btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);
@@ -3320,10 +3341,9 @@ static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type)
 
     bt_bdaddr_t bd_addr;
     bdcpy(bd_addr.address, req_oob_type->bd_addr);
-
-    /* We currently support only Security Manager TK as OOB data. We already
-     * checked if it's present in btif_dm_set_oob_for_le_io_req, but check here
-     * again. If it's not present do nothing, pairing will timeout.
+    /* We already checked if OOB data is present in
+     * btif_dm_set_oob_for_le_io_req, but check here again. If it's not present
+     * do nothing, pairing will timeout.
      */
     if (is_empty_128bit(oob_cb.oob_data.sm_tk)) {
         return;
@@ -3347,6 +3367,44 @@ static void btif_dm_ble_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type)
     BTM_BleOobDataReply(req_oob_type->bd_addr, 0, 16, oob_cb.oob_data.sm_tk);
 }
 
+
+static void btif_dm_ble_sc_oob_req_evt(tBTA_DM_SP_RMT_OOB *req_oob_type)
+{
+    BTIF_TRACE_DEBUG("%s", __func__);
+
+    bt_bdaddr_t bd_addr;
+    bdcpy(bd_addr.address, req_oob_type->bd_addr);
+
+    /* We already checked if OOB data is present in
+     * btif_dm_set_oob_for_le_io_req, but check here again. If it's not present
+     * do nothing, pairing will timeout.
+     */
+    if (is_empty_128bit(oob_cb.oob_data.le_sc_c) &&
+        is_empty_128bit(oob_cb.oob_data.le_sc_r)) {
+        BTIF_TRACE_WARNING("%s: LE SC OOB data is empty", __func__);
+        return;
+    }
+
+    /* make sure OOB data is for this particular device */
+    if (memcmp(req_oob_type->bd_addr, oob_cb.bdaddr, BD_ADDR_LEN) != 0) {
+        BTIF_TRACE_WARNING("%s: remote address didn't match OOB data address", __func__);
+        return;
+    }
+
+    /* Remote name update */
+    btif_update_remote_properties(req_oob_type->bd_addr , req_oob_type->bd_name,
+                                          NULL, BT_DEVICE_TYPE_BLE);
+
+    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+    pairing_cb.is_ssp = false;
+    pairing_cb.is_le_only = true; //TODO: we can derive classic pairing from this one
+    pairing_cb.is_le_nc = false;
+
+    BTM_BleSecureConnectionOobDataReply(req_oob_type->bd_addr,
+                                        oob_cb.oob_data.le_sc_c,
+                                        oob_cb.oob_data.le_sc_r);
+}
+
 void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
                                            tBT_DEVICE_TYPE dev_type)
 {
@@ -3488,7 +3546,7 @@ static void btif_stats_add_bond_event(const bt_bdaddr_t *bd_addr,
     uint32_t cod = get_cod(bd_addr);
     uint64_t ts = event->timestamp.tv_sec * 1000 +
                   event->timestamp.tv_nsec / 1000000;
-    metrics_pair_event(0, ts, cod, device_type);
+    metrics_log_pair_event(0, ts, cod, device_type);
 
     pthread_mutex_unlock(&bond_event_lock);
 }
index f27f4bd..7ad4f08 100644 (file)
@@ -50,9 +50,8 @@
 #include "btif_gatt_multi_adv_util.h"
 #include "btif_gatt_util.h"
 #include "btif_storage.h"
+#include "btif_storage.h"
 #include "osi/include/log.h"
-#include "osi/include/alarm.h"
-#include "stack/include/gatt_api.h"
 #include "vendor_api.h"
 
 /*******************************************************************************
@@ -70,7 +69,6 @@
 #define BLE_RESOLVE_ADDR_MSB                 0x40   /* bit7, bit6 is 01 to be resolvable random */
 #define BLE_RESOLVE_ADDR_MASK                0xc0   /* bit 6, and bit7 */
 #define BTM_BLE_IS_RESOLVE_BDA(x)           ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
-#define BT_CONN_PARAM_UPDATE_STATUS          1010003
 
 typedef enum {
     BTIF_GATTC_REGISTER_APP = 1000,
@@ -208,15 +206,12 @@ typedef struct
 
 typedef struct
 {
-    uint8_t     client_if;
     bt_bdaddr_t bd_addr;
-    uint16_t    requested_min_interval;
-    uint16_t    requested_max_interval;
-    uint16_t    configured_interval;
+    uint16_t    min_interval;
+    uint16_t    max_interval;
     uint16_t    timeout;
     uint16_t    latency;
-    uint8_t     status;
-}__attribute__((packed)) btif_conn_param_cb_t;
+} btif_conn_param_cb_t;
 
 typedef struct
 {
@@ -241,138 +236,6 @@ static btif_gattc_dev_cb_t  *p_dev_cb = &btif_gattc_dev_cb;
 static uint8_t rssi_request_client_if;
 
 /*******************************************************************************
-**  Auto Connection Parameter Update
-**
-**  Feature is enabled when WEAR_AUTO_CONN_PARAM_UPDATE build config is set to
-**  TRUE.  It looks for a whitelisted address in the configuration file and
-**  automatically applies a connection interval parameter update
-**  (WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS) when the connection is idle for a
-**  specific period of time (WEAR_AUTO_CONN_IDLE_TIMEOUT_MS).
-********************************************************************************/
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-typedef struct
-{
-    bt_bdaddr_t device_address;
-    uint16_t    min_interval;
-    uint16_t    max_interval;
-    uint16_t    timeout;
-    uint16_t    latency;
-    bool        is_auto_update_address_known;
-    bool        is_auto_update_enabled;
-    bool        is_updating;
-    alarm_t     *check_idle_alarm;
-} btgatt_auto_connection_param_update_cb_t;
-
-static btgatt_auto_connection_param_update_cb_t auto_conn_param_update_cb;
-
-static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *bd_addr, int min_interval,
-             int max_interval, int latency, int timeout);
-
-static void auto_connection_param_update_idle_cb(UNUSED_ATTR void *data)
-{
-    btgatt_auto_connection_param_update_cb_t *auto_update_cb =
-        (btgatt_auto_connection_param_update_cb_t *)data;
-
-    if (auto_conn_param_update_cb.is_updating)
-    {
-        LOG_WARN(LOG_TAG, "%s another connection update in progress", __FUNCTION__);
-        return;
-    }
-
-    btif_gattc_conn_parameter_update_internal(&auto_update_cb->device_address,
-        WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS, WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS, 0, 2000);
-    LOG_INFO(LOG_TAG, "%s auto adjust connection interval to %dms", __FUNCTION__,
-             (int)(WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS * 1.25f));
-}
-
-static void maybe_set_connection_param_update_in_progress(const bt_bdaddr_t *bd_addr, bool in_progress)
-{
-    if (auto_conn_param_update_cb.is_auto_update_enabled &&
-        bdcmp(auto_conn_param_update_cb.device_address.address, bd_addr->address) == 0)
-    {
-        auto_conn_param_update_cb.is_updating = in_progress;
-    }
-}
-
-static void maybe_enable_auto_connection_param_update(const bt_bdaddr_t *bd_addr, int min_interval,
-                                                      int max_interval, int latency, int timeout)
-{
-    /* First check if there is a whitelisted address to enable auto connection param update */
-    if (!auto_conn_param_update_cb.is_auto_update_address_known)
-    {
-        bdstr_t bdstr;
-        int bdstr_size = sizeof(bdstr);
-        /*
-         * If AutoConnParamUpdateAddr is not set from bonding, infer the first LE address performing
-         * connection parameter update as the companion.
-         */
-        if (!btif_config_get_str("Adapter", "AutoConnParamUpdateAddr", bdstr, &bdstr_size)) {
-            bdaddr_to_string(bd_addr, bdstr, bdstr_size);
-            btif_config_set_str("Adapter", "AutoConnParamUpdateAddr", bdstr);
-            LOG_INFO(LOG_TAG, "%s force set AutoConnParamUpdateAddr: %s", __FUNCTION__, bdstr);
-        }
-
-        bdcpy(auto_conn_param_update_cb.device_address.address, bd_addr->address);
-        auto_conn_param_update_cb.is_auto_update_address_known = true;
-        LOG_INFO(LOG_TAG, "%s auto connection param update for address: %s", __FUNCTION__, bdstr);
-    }
-
-    /* If the address matches the auto update address, store the connection parameter value */
-    if (bdcmp(auto_conn_param_update_cb.device_address.address, bd_addr->address) == 0)
-    {
-        auto_conn_param_update_cb.min_interval = min_interval;
-        auto_conn_param_update_cb.max_interval = max_interval;
-        auto_conn_param_update_cb.timeout = timeout;
-        auto_conn_param_update_cb.latency = latency;
-        auto_conn_param_update_cb.is_auto_update_enabled = true;
-    }
-}
-
-static void maybe_restore_connection_parameters(BD_ADDR address) {
-    /*
-     * Will not perform auto connection parameter update if:
-     *
-     * - feature not enabled (yet)
-     * - address doesn't match auto update address
-     * - connection parameter update is in progress
-     */
-    if (!auto_conn_param_update_cb.is_auto_update_enabled ||
-        (bdcmp(auto_conn_param_update_cb.device_address.address, address) != 0) ||
-        auto_conn_param_update_cb.is_updating)
-    {
-        return;
-    }
-
-    if (alarm_is_scheduled(auto_conn_param_update_cb.check_idle_alarm))
-    {
-        /* Idle alarm is scheduled, reschedule it */
-        alarm_cancel(auto_conn_param_update_cb.check_idle_alarm);
-    }
-    else
-    {
-        /* No idle alarm and no update in progress, restore specified connection parameters */
-        btif_gattc_conn_parameter_update_internal(&auto_conn_param_update_cb.device_address,
-                                                  auto_conn_param_update_cb.min_interval,
-                                                  auto_conn_param_update_cb.max_interval,
-                                                  auto_conn_param_update_cb.latency,
-                                                  auto_conn_param_update_cb.timeout);
-        LOG_VERBOSE(LOG_TAG, "%s restore connection parameters", __FUNCTION__);
-    }
-
-    /* Schedule idle alarm */
-    if (!auto_conn_param_update_cb.check_idle_alarm)
-    {
-        auto_conn_param_update_cb.check_idle_alarm =
-            alarm_new("gatt_client.auto_conn_param_update_idle_alarm");
-    }
-    alarm_set(auto_conn_param_update_cb.check_idle_alarm, WEAR_AUTO_CONN_IDLE_TIMEOUT_MS,
-              auto_connection_param_update_idle_cb, &auto_conn_param_update_cb);
-
-    return;
-}
-#endif
-
-/*******************************************************************************
 **  Static functions
 ********************************************************************************/
 
@@ -673,10 +536,6 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
             if (p_data->notify.is_notify == FALSE)
                 BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
 
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-            maybe_restore_connection_parameters(data.bda.address);
-#endif
-
             break;
         }
 
@@ -940,20 +799,6 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
             break;
         }
 
-        case BTA_GATTC_CONN_PARAM_UPD_EVT:
-        {
-            btif_conn_param_cb_t *p_btif_cb = (btif_conn_param_cb_t *)p_param;
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-            maybe_set_connection_param_update_in_progress(&p_btif_cb->bd_addr, false);
-#endif
-            /* Log update failures */
-            if (p_btif_cb->status != 0)
-            {
-                LOG_EVENT_INT(BT_CONN_PARAM_UPDATE_STATUS, p_btif_cb->status);
-            }
-            break;
-        }
-
         case BTIF_GATTC_SCAN_PARAM_EVT:
         {
             btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t *)p_param;
@@ -1247,20 +1092,6 @@ static void bta_scan_filt_status_cb(UINT8 action, tBTA_STATUS status,
                           (char*) &btif_cb, sizeof(btgatt_adv_filter_cb_t), NULL);
 }
 
-static void bta_gattc_conn_param_update_cback(BD_ADDR bd_addr, UINT16 interval,
-                                              UINT16 latency, UINT16 timeout, tBTA_STATUS status)
-{
-    btif_conn_param_cb_t btif_cb;
-
-    bdcpy(btif_cb.bd_addr.address, bd_addr);
-    btif_cb.configured_interval = interval;
-    btif_cb.latency = latency;
-    btif_cb.timeout = timeout;
-    btif_cb.status = status;
-    btif_transfer_context(btif_gattc_upstreams_evt, BTA_GATTC_CONN_PARAM_UPD_EVT,
-                          (char*) &btif_cb, sizeof(btif_conn_param_cb_t), NULL);
-}
-
 static void btgattc_free_event_data(UINT16 event, char *event_data)
 {
     switch (event)
@@ -1423,21 +1254,9 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
             break;
 
         case BTIF_GATTC_WRITE_CHAR:
-        {
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-            /* TODO(jackyc): find a cleaner way to get address from connection id */
-            tGATT_IF gatt_if;
-            BD_ADDR bd_addr;
-            tBT_TRANSPORT transport;
-            if (GATT_GetConnectionInfor(p_cb->conn_id, &gatt_if, bd_addr, &transport) == TRUE)
-            {
-                maybe_restore_connection_parameters(bd_addr);
-            }
-#endif
             BTA_GATTC_WriteCharValue(p_cb->conn_id, p_cb->handle, p_cb->write_type,
                                      p_cb->len, p_cb->value, p_cb->auth_req);
             break;
-        }
 
         case BTIF_GATTC_WRITE_CHAR_DESCR:
             descr_val.len = p_cb->len;
@@ -1734,14 +1553,11 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
             if (BTA_DmGetConnectionState(p_conn_param_cb->bd_addr.address))
             {
                 BTA_DmBleUpdateConnectionParams(p_conn_param_cb->bd_addr.address,
-                               p_conn_param_cb->requested_min_interval,
-                               p_conn_param_cb->requested_max_interval,
-                               p_conn_param_cb->latency, p_conn_param_cb->timeout,
-                               bta_gattc_conn_param_update_cback);
+                               p_conn_param_cb->min_interval, p_conn_param_cb->max_interval,
+                               p_conn_param_cb->latency, p_conn_param_cb->timeout);
             } else {
                 BTA_DmSetBlePrefConnParams(p_conn_param_cb->bd_addr.address,
-                               p_conn_param_cb->requested_min_interval,
-                               p_conn_param_cb->requested_max_interval,
+                               p_conn_param_cb->min_interval, p_conn_param_cb->max_interval,
                                p_conn_param_cb->latency, p_conn_param_cb->timeout);
             }
             break;
@@ -2057,16 +1873,13 @@ static bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu)
                                  (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
 }
 
-static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *bd_addr, int min_interval,
-                                                    int max_interval, int latency, int timeout)
+static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, int min_interval,
+                    int max_interval, int latency, int timeout)
 {
     CHECK_BTGATT_INIT();
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-    maybe_set_connection_param_update_in_progress(bd_addr, true);
-#endif
     btif_conn_param_cb_t btif_cb;
-    btif_cb.requested_min_interval = min_interval;
-    btif_cb.requested_max_interval = max_interval;
+    btif_cb.min_interval = min_interval;
+    btif_cb.max_interval = max_interval;
     btif_cb.latency = latency;
     btif_cb.timeout = timeout;
     bdcpy(btif_cb.bd_addr.address, bd_addr->address);
@@ -2074,16 +1887,6 @@ static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *
                                  (char*) &btif_cb, sizeof(btif_conn_param_cb_t), NULL);
 }
 
-static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, int min_interval,
-                                                    int max_interval, int latency, int timeout)
-{
-#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
-    maybe_enable_auto_connection_param_update(bd_addr, min_interval, max_interval, latency, timeout);
-#endif
-
-    return btif_gattc_conn_parameter_update_internal(bd_addr, min_interval, max_interval, latency, timeout);
-}
-
 static bt_status_t btif_gattc_scan_filter_param_setup(btgatt_filt_param_setup_t
                                                       filt_param)
 {
index 4e23f3f..9d963d1 100644 (file)
@@ -1152,14 +1152,6 @@ static bt_status_t bind_response(bthf_hf_ind_type_t ind_id, bthf_hf_ind_status_t
     return BT_STATUS_SUCCESS;
 }
 
-static bt_status_t set_sco_allowed(bool value)
-{
-    CHECK_BTHF_INIT();
-
-    BTA_AgSetScoAllowed(value);
-    return BT_STATUS_SUCCESS;
-}
-
 /*******************************************************************************
 **
 ** Function         formatted_at_response
@@ -1651,7 +1643,6 @@ static const bthf_interface_t bthfInterface = {
     cleanup,
     configure_wbs,
     bind_response,
-    set_sco_allowed,
 };
 
 /*******************************************************************************
index ef3d4fb..cf464e1 100644 (file)
@@ -245,6 +245,7 @@ typedef struct {
 
 typedef struct {
     uint64_t session_start_us;
+    uint64_t session_end_us;
 
     scheduling_stats_t tx_queue_enqueue_stats;
     scheduling_stats_t tx_queue_dequeue_stats;
@@ -262,6 +263,7 @@ typedef struct {
     uint64_t tx_queue_last_flushed_us;
 
     size_t tx_queue_total_dropped_messages;
+    size_t tx_queue_max_dropped_messages;
     size_t tx_queue_dropouts;
     uint64_t tx_queue_last_dropouts_us;
 
@@ -335,6 +337,7 @@ typedef struct
     alarm_t *media_alarm;
     alarm_t *decode_alarm;
     btif_media_stats_t stats;
+    btif_media_stats_t accumulated_stats;
 #endif
 } tBTIF_MEDIA_CB;
 
@@ -410,6 +413,68 @@ static thread_t *worker_thread;
 /*****************************************************************************
  **  Misc helper functions
  *****************************************************************************/
+void btif_a2dp_source_accumulate_scheduling_stats(scheduling_stats_t* src,
+                                                  scheduling_stats_t* dst) {
+    dst->total_updates += src->total_updates;
+    dst->last_update_us = src->last_update_us;
+    dst->overdue_scheduling_count += src->overdue_scheduling_count;
+    dst->total_overdue_scheduling_delta_us += src->total_overdue_scheduling_delta_us;
+    if (src->max_overdue_scheduling_delta_us > dst->max_overdue_scheduling_delta_us) {
+        dst->max_overdue_scheduling_delta_us = src->max_overdue_scheduling_delta_us;
+    }
+    dst->premature_scheduling_count += src->premature_scheduling_count;
+    dst->total_premature_scheduling_delta_us += src->total_premature_scheduling_delta_us;
+    if (src->max_premature_scheduling_delta_us > dst->max_premature_scheduling_delta_us) {
+        dst->max_premature_scheduling_delta_us = src->max_premature_scheduling_delta_us;
+    }
+    dst->exact_scheduling_count += src->exact_scheduling_count;
+    dst->total_scheduling_time_us += src->total_scheduling_time_us;
+}
+
+void btif_a2dp_source_accumulate_stats(btif_media_stats_t* src,
+                                       btif_media_stats_t* dst) {
+    dst->tx_queue_total_frames += src->tx_queue_total_frames;
+    if (src->tx_queue_max_frames_per_packet > dst->tx_queue_max_frames_per_packet) {
+        dst->tx_queue_max_frames_per_packet = src->tx_queue_max_frames_per_packet;
+    }
+    dst->tx_queue_total_queueing_time_us += src->tx_queue_total_queueing_time_us;
+    if (src->tx_queue_max_queueing_time_us > dst->tx_queue_max_queueing_time_us) {
+        dst->tx_queue_max_queueing_time_us = src->tx_queue_max_queueing_time_us;
+    }
+    dst->tx_queue_total_readbuf_calls += src->tx_queue_total_readbuf_calls;
+    dst->tx_queue_last_readbuf_us = src->tx_queue_last_readbuf_us;
+    dst->tx_queue_total_flushed_messages += src->tx_queue_total_flushed_messages;
+    dst->tx_queue_last_flushed_us = src->tx_queue_last_flushed_us;
+    dst->tx_queue_total_dropped_messages += src->tx_queue_total_dropped_messages;
+    if (src->tx_queue_max_dropped_messages > dst->tx_queue_max_dropped_messages) {
+        dst->tx_queue_max_dropped_messages = src->tx_queue_max_dropped_messages;
+    }
+    dst->tx_queue_dropouts += src->tx_queue_dropouts;
+    dst->tx_queue_last_dropouts_us = src->tx_queue_last_dropouts_us;
+    dst->media_read_total_underflow_bytes +=
+      src->media_read_total_underflow_bytes;
+    dst->media_read_total_underflow_count +=
+      src->media_read_total_underflow_count;
+    dst->media_read_last_underflow_us = src->media_read_last_underflow_us;
+    dst->media_read_total_underrun_bytes += src->media_read_total_underrun_bytes;
+    dst->media_read_total_underflow_count += src->media_read_total_underrun_count;
+    dst->media_read_last_underrun_us = src->media_read_last_underrun_us;
+    dst->media_read_total_expected_frames += src->media_read_total_expected_frames;
+    if (src->media_read_max_expected_frames > dst->media_read_max_expected_frames) {
+        dst->media_read_max_expected_frames = src->media_read_max_expected_frames;
+    }
+    dst->media_read_expected_count += src->media_read_expected_count;
+    dst->media_read_total_limited_frames += src->media_read_total_limited_frames;
+    if (src->media_read_max_limited_frames > dst->media_read_max_limited_frames) {
+        dst->media_read_max_limited_frames = src->media_read_max_limited_frames;
+    }
+    dst->media_read_limited_count += src->media_read_limited_count;
+    btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_enqueue_stats,
+                                               &dst->tx_queue_enqueue_stats);
+    btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_dequeue_stats,
+                                               &dst->tx_queue_dequeue_stats);
+    memset(src, 0, sizeof(btif_media_stats_t));
+}
 
 static void update_scheduling_stats(scheduling_stats_t *stats,
                                     uint64_t now_us, uint64_t expected_delta)
@@ -1406,6 +1471,9 @@ static void btif_media_task_aa_handle_timer(UNUSED_ATTR void *context)
     if (alarm_is_scheduled(btif_media_cb.media_alarm))
     {
         btif_media_send_aa_frame(timestamp_us);
+        update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats,
+                                timestamp_us,
+                                BTIF_SINK_MEDIA_TIME_TICK_MS * 1000);
     }
     else
     {
@@ -1432,7 +1500,6 @@ static void btif_media_thread_init(UNUSED_ATTR void *context) {
   assert(CHAR_BIT == 8);
 
   memset(&btif_media_cb, 0, sizeof(btif_media_cb));
-  btif_media_cb.stats.session_start_us = time_now_us();
 
   UIPC_Init(NULL);
 
@@ -1444,6 +1511,7 @@ static void btif_media_thread_init(UNUSED_ATTR void *context) {
 
   raise_priority_a2dp(TASK_HIGH_MEDIA);
   media_task_running = MEDIA_TASK_STATE_ON;
+  metrics_log_bluetooth_session_start(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
 }
 
 static void btif_media_thread_cleanup(UNUSED_ATTR void *context) {
@@ -1462,6 +1530,7 @@ static void btif_media_thread_cleanup(UNUSED_ATTR void *context) {
 
   /* Clear media task flag */
   media_task_running = MEDIA_TASK_STATE_OFF;
+  metrics_log_bluetooth_session_end(DISCONNECT_REASON_UNKNOWN, 0);
 }
 
 /*******************************************************************************
@@ -1701,6 +1770,14 @@ BOOLEAN btif_media_task_start_aa_req(void)
     p_buf->event = BTIF_MEDIA_START_AA_TX;
     fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    memset(&btif_media_cb.stats, 0, sizeof(btif_media_stats_t));
+    // Assign session_start_us to 1 when time_now_us() is 0 to indicate
+    // btif_media_task_start_aa_req() has been called
+    btif_media_cb.stats.session_start_us = time_now_us();
+    if (btif_media_cb.stats.session_start_us == 0) {
+        btif_media_cb.stats.session_start_us = 1;
+    }
+    btif_media_cb.stats.session_end_us = 0;
     return TRUE;
 }
 
@@ -1729,8 +1806,14 @@ BOOLEAN btif_media_task_stop_aa_req(void)
      * the "cleanup() -> btif_a2dp_stop_media_task()" processing during
      * the shutdown of the Bluetooth stack.
      */
-    if (btif_media_cmd_msg_queue != NULL)
+    if (btif_media_cmd_msg_queue != NULL) {
         fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    }
+
+    btif_media_cb.stats.session_end_us = time_now_us();
+    btif_update_a2dp_metrics();
+    btif_a2dp_source_accumulate_stats(&btif_media_cb.stats,
+        &btif_media_cb.accumulated_stats);
 
     return TRUE;
 }
@@ -3079,9 +3162,6 @@ static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame,
             }
 
             /* Enqueue the encoded SBC frame in AA Tx Queue */
-            update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats,
-                                    timestamp_us,
-                                    BTIF_SINK_MEDIA_TIME_TICK_MS * 1000);
             uint8_t done_nb_frame = remain_nb_frame - nb_frame;
             remain_nb_frame = nb_frame;
             btif_media_cb.stats.tx_queue_total_frames += done_nb_frame;
@@ -3124,6 +3204,10 @@ static void btif_media_aa_prep_2_send(UINT8 nb_frame, uint64_t timestamp_us)
         btif_media_cb.stats.tx_queue_last_dropouts_us = timestamp_us;
 
         // Flush all queued buffers...
+        size_t drop_n = fixed_queue_length(btif_media_cb.TxAaQ);
+        if (drop_n > btif_media_cb.stats.tx_queue_max_dropped_messages) {
+            btif_media_cb.stats.tx_queue_max_dropped_messages = drop_n;
+        }
         while (fixed_queue_length(btif_media_cb.TxAaQ)) {
             btif_media_cb.stats.tx_queue_total_dropped_messages++;
             osi_free(fixed_queue_try_dequeue(btif_media_cb.TxAaQ));
@@ -3255,8 +3339,10 @@ void dump_codec_info(unsigned char *p_codec)
 
 void btif_debug_a2dp_dump(int fd)
 {
+    btif_a2dp_source_accumulate_stats(&btif_media_cb.stats,
+                                    &btif_media_cb.accumulated_stats);
     uint64_t now_us = time_now_us();
-    btif_media_stats_t *stats = &btif_media_cb.stats;
+    btif_media_stats_t *stats = &btif_media_cb.accumulated_stats;
     scheduling_stats_t *enqueue_stats = &stats->tx_queue_enqueue_stats;
     scheduling_stats_t *dequeue_stats = &stats->tx_queue_dequeue_stats;
     size_t ave_size;
@@ -3390,52 +3476,51 @@ void btif_debug_a2dp_dump(int fd)
 
 void btif_update_a2dp_metrics(void)
 {
-    uint64_t now_us = time_now_us();
-    btif_media_stats_t *stats = &btif_media_cb.stats;
-    scheduling_stats_t *dequeue_stats = &stats->tx_queue_dequeue_stats;
-    int32_t media_timer_min_ms = 0;
-    int32_t media_timer_max_ms = 0;
-    int32_t media_timer_avg_ms = 0;
-    int32_t buffer_overruns_max_count = 0;
-    int32_t buffer_overruns_total = 0;
-    float buffer_underruns_average = 0.0;
-    int32_t buffer_underruns_count = 0;
-
-    int64_t session_duration_sec =
-        (now_us - stats->session_start_us) / (1000 * 1000);
-
-    /* NOTE: Disconnect reason is unused */
-    const char *disconnect_reason = NULL;
-    uint32_t device_class = BTM_COD_MAJOR_AUDIO;
-
-    if (dequeue_stats->total_updates > 1) {
-        media_timer_min_ms = BTIF_SINK_MEDIA_TIME_TICK_MS -
-            (dequeue_stats->max_premature_scheduling_delta_us / 1000);
-        media_timer_max_ms = BTIF_SINK_MEDIA_TIME_TICK_MS +
-            (dequeue_stats->max_overdue_scheduling_delta_us / 1000);
-
-        uint64_t total_scheduling_count =
-            dequeue_stats->overdue_scheduling_count +
-            dequeue_stats->premature_scheduling_count +
-            dequeue_stats->exact_scheduling_count;
-        if (total_scheduling_count > 0) {
-            media_timer_avg_ms = dequeue_stats->total_scheduling_time_us /
-                (1000 * total_scheduling_count);
+    btif_media_stats_t* stats = &btif_media_cb.stats;
+    scheduling_stats_t* enqueue_stats = &stats->tx_queue_enqueue_stats;
+    A2dpSessionMetrics_t metrics;
+    metrics.media_timer_min_ms = -1;
+    metrics.media_timer_max_ms = -1;
+    metrics.media_timer_avg_ms = -1;
+    metrics.total_scheduling_count = -1;
+    metrics.buffer_overruns_max_count = -1;
+    metrics.buffer_overruns_total = -1;
+    metrics.buffer_underruns_average = -1.0;
+    metrics.buffer_underruns_count = -1;
+    metrics.audio_duration_ms = -1;
+    // session_start_us is 0 when btif_media_task_start_aa_req() is not called
+    // mark the metric duration as invalid (-1) in this case
+    if (stats->session_start_us != 0) {
+        int64_t session_end_us = stats->session_end_us == 0
+                               ? time_now_us()
+                               : stats->session_end_us;
+        metrics.audio_duration_ms = (session_end_us - stats->session_start_us) / 1000;
+    }
+    if (enqueue_stats->total_updates > 1) {
+        metrics.media_timer_min_ms = BTIF_SINK_MEDIA_TIME_TICK_MS -
+            (enqueue_stats->max_premature_scheduling_delta_us / 1000);
+        metrics.media_timer_max_ms = BTIF_SINK_MEDIA_TIME_TICK_MS +
+            (enqueue_stats->max_overdue_scheduling_delta_us / 1000);
+        metrics.total_scheduling_count
+            = enqueue_stats->overdue_scheduling_count +
+                enqueue_stats->premature_scheduling_count +
+                    enqueue_stats->exact_scheduling_count;
+        if (metrics.total_scheduling_count > 0) {
+            metrics.media_timer_avg_ms = enqueue_stats->total_scheduling_time_us /
+                (1000 * metrics.total_scheduling_count);
         }
-
-        buffer_overruns_max_count = stats->media_read_max_expected_frames;
-        buffer_overruns_total = stats->tx_queue_total_dropped_messages;
-        buffer_underruns_count = stats->media_read_total_underflow_count +
-            stats->media_read_total_underrun_count;
-        if (buffer_underruns_count > 0) {
-            buffer_underruns_average =
-                (stats->media_read_total_underflow_bytes + stats->media_read_total_underrun_bytes) / buffer_underruns_count;
+        metrics.buffer_overruns_max_count = stats->tx_queue_max_dropped_messages;
+        metrics.buffer_overruns_total = stats->tx_queue_total_dropped_messages;
+        metrics.buffer_underruns_count =
+            stats->media_read_total_underflow_count +
+                stats->media_read_total_underrun_count;
+        metrics.buffer_underruns_average = 0;
+        if (metrics.buffer_underruns_count > 0) {
+            metrics.buffer_underruns_average =
+                (stats->media_read_total_underflow_bytes +
+                    stats->media_read_total_underrun_bytes) /
+                        metrics.buffer_underruns_count;
         }
     }
-
-    metrics_a2dp_session(session_duration_sec, disconnect_reason, device_class,
-                         media_timer_min_ms, media_timer_max_ms,
-                         media_timer_avg_ms, buffer_overruns_max_count,
-                         buffer_overruns_total, buffer_underruns_average,
-                         buffer_underruns_count);
+    metrics_log_a2dp_session(&metrics);
 }
index 9fb623a..468c6f0 100644 (file)
@@ -54,8 +54,6 @@
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
-#include "device/include/controller.h"
-
 /************************************************************************************
 **  Constants & Macros
 ************************************************************************************/
 /* This is a local property to add a device found */
 #define BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP 0xFF
 
-// TODO: This macro should be converted to a function
-#define BTIF_STORAGE_GET_ADAPTER_PROP(s, t,v,l,p) \
-      {p.type=t;p.val=v;p.len=l; s = btif_storage_get_adapter_property(&p);}
+#define BTIF_STORAGE_GET_ADAPTER_PROP(t,v,l,p) \
+      {p.type=t;p.val=v;p.len=l; btif_storage_get_adapter_property(&p);}
 
-// TODO: This macro should be converted to a function
 #define BTIF_STORAGE_GET_REMOTE_PROP(b,t,v,l,p) \
       {p.type=t;p.val=v;p.len=l;btif_storage_get_remote_device_property(b,&p);}
 
@@ -593,17 +589,8 @@ bt_status_t btif_storage_get_adapter_property(bt_property_t *property)
     if (property->type == BT_PROPERTY_BDADDR)
     {
         bt_bdaddr_t *bd_addr = (bt_bdaddr_t*)property->val;
-        /* Fetch the local BD ADDR */
-        const controller_t* controller = controller_get_interface();
-        if (controller->get_is_ready() == false) {
-          BTIF_TRACE_DEBUG("%s: Controller not ready! Unable to return Bluetooth Address",
-                    __FUNCTION__);
-          memset(bd_addr, 0, sizeof(bt_bdaddr_t));
-          return BT_STATUS_FAIL;
-        } else {
-          BTIF_TRACE_DEBUG("%s: Controller ready!", __FUNCTION__);
-          memcpy(bd_addr, controller->get_address(), sizeof(bt_bdaddr_t));
-        }
+        /* This has been cached in btif. Just fetch it from there */
+        memcpy(bd_addr, &btif_local_bd_addr, sizeof(bt_bdaddr_t));
         property->len = sizeof(bt_bdaddr_t);
         return BT_STATUS_SUCCESS;
     }
@@ -914,7 +901,6 @@ bt_status_t btif_storage_load_bonded_devices(void)
     uint32_t disc_timeout;
     bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
     bt_uuid_t remote_uuids[BT_MAX_NUM_UUIDS];
-    bt_status_t status;
 
     remove_devices_with_sample_ltk();
 
@@ -925,16 +911,12 @@ bt_status_t btif_storage_load_bonded_devices(void)
         memset(adapter_props, 0, sizeof(adapter_props));
 
         /* BD_ADDR */
-        BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_BDADDR, &addr, sizeof(addr),
+        BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_BDADDR, &addr, sizeof(addr),
                                       adapter_props[num_props]);
-        // Add BT_PROPERTY_BDADDR property into list only when successful.
-        // Otherwise, skip this property entry.
-        if (status == BT_STATUS_SUCCESS) {
-          num_props++;
-        }
+        num_props++;
 
         /* BD_NAME */
-        BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_BDNAME, &name, sizeof(name),
+        BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_BDNAME, &name, sizeof(name),
                                       adapter_props[num_props]);
         num_props++;
 
@@ -950,7 +932,7 @@ bt_status_t btif_storage_load_bonded_devices(void)
         num_props++;
 
         /* DISC_TIMEOUT */
-        BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+        BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
                                       &disc_timeout, sizeof(disc_timeout),
                                       adapter_props[num_props]);
         num_props++;
@@ -968,7 +950,7 @@ bt_status_t btif_storage_load_bonded_devices(void)
         num_props++;
 
         /* LOCAL UUIDs */
-        BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_UUIDS,
+        BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_UUIDS,
                                       local_uuids, sizeof(local_uuids),
                                       adapter_props[num_props]);
         num_props++;
index 3a7f48b..a0afcb5 100644 (file)
@@ -3,7 +3,7 @@
 BtSnoopLogOutput=false
 
 # BtSnoop log output file
-BtSnoopFileName=/sdcard/btsnoop_hci.log
+BtSnoopFileName=/data/misc/bluetooth/logs/btsnoop_hci.log
 
 # Preserve existing BtSnoop log before overwriting
 BtSnoopSaveLog=false
index 76a83fc..05778a8 100644 (file)
@@ -54,7 +54,16 @@ typedef enum {
   // Keyboards should use a variable pin at all times. However, some keyboards
   // require a fixed pin of all 0000. This workaround enables auto pairing for
   // those keyboards.
-  INTEROP_KEYBOARD_REQUIRES_FIXED_PIN
+  INTEROP_KEYBOARD_REQUIRES_FIXED_PIN,
+
+  // Some headsets have audio jitter issues because of increased re-transmissions as the
+  // 3 Mbps packets have a lower link margin, and are more prone to interference. We can
+  // disable 3DH packets (use only 2DH packets) for the ACL link to improve sensitivity
+  // when streaming A2DP audio to the headset. Air sniffer logs show reduced
+  // re-transmissions after switching to 2DH packets.
+  //
+  // Disable 3Mbps packets and use only 2Mbps packets for ACL links when streaming audio.
+  INTEROP_2MBPS_LINK_ONLY
 } interop_feature_t;
 
 // Check if a given |addr| matches a known interoperability workaround as identified
index 77e0450..49cb8a5 100644 (file)
@@ -55,6 +55,9 @@ static const interop_addr_entry_t interop_addr_database[] = {
   {{{0x44, 0x5e, 0xf3,      0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
   {{{0xd4, 0x9c, 0x28,      0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
 
+  // JayBird Family
+  {{{0x00, 0x18, 0x91,      0,0,0}}, 3, INTEROP_2MBPS_LINK_ONLY},
+
   // LG Tone HBS-730 - unacceptably loud volume
   {{{0x00, 0x18, 0x6b,      0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
   {{{0xb8, 0xad, 0x3e,      0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
index 8e59394..50020f7 100644 (file)
@@ -114,6 +114,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) {
     CASE_RETURN_STR(INTEROP_DISABLE_ABSOLUTE_VOLUME)
     CASE_RETURN_STR(INTEROP_DISABLE_AUTO_PAIRING)
     CASE_RETURN_STR(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN)
+    CASE_RETURN_STR(INTEROP_2MBPS_LINK_ONLY)
   }
 
   return "UNKNOWN";
index 9e53b61..dbc9bb2 100644 (file)
@@ -143,8 +143,7 @@ static uint64_t btsnoop_timestamp(void) {
   gettimeofday(&tv, NULL);
 
   // Timestamp is in microseconds.
-  uint64_t timestamp = tv.tv_sec;
-  timestamp *= (uint64_t)1000000ULL;
+  uint64_t timestamp = tv.tv_sec * 1000 * 1000LL;
   timestamp += tv.tv_usec;
   timestamp += BTSNOOP_EPOCH_DELTA;
   return timestamp;
@@ -172,12 +171,15 @@ static void update_logging() {
         LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__, log_path, last_log_path, strerror(errno));
     }
 
+    mode_t prevmask = umask(0);
     logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
     if (logfile_fd == INVALID_FD) {
       LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path, strerror(errno));
       is_logging = false;
+      umask(prevmask);
       return;
     }
+    umask(prevmask);
 
     write(logfile_fd, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16);
   } else {
index c339d9f..184a6cd 100644 (file)
@@ -1563,41 +1563,7 @@ The maximum number of payload octets that the local device can receive in a sing
 
 /* Enable/disable LE IO capability overriding to no-input-no-output on first bond */
 #ifndef WEAR_LE_IO_CAP_OVERRIDE
-#define WEAR_LE_IO_CAP_OVERRIDE               FALSE
-#endif
-
-/*
- * Enable/disable LE auto connection parameter update.
- * When enabled, the first bonded device that is also of type LE will be whitelisted
- * to use auto connection parameter update.
- */
-#ifndef WEAR_AUTO_CONN_PARAM_UPDATE
-#define WEAR_AUTO_CONN_PARAM_UPDATE           FALSE
-#endif
-
-/*
- * Idle timeout period in milliseconds for auto connection parameter update.
- * Only used when WEAR_AUTO_CONN_PARAM_UPDATE is enabled.
- */
-#ifndef WEAR_AUTO_CONN_IDLE_TIMEOUT_MS
-#define WEAR_AUTO_CONN_IDLE_TIMEOUT_MS        10000
-#endif
-
-/*
- * Connection interval parameter applied when the connection is detected to be idle for
- * WEAR_AUTO_CONN_IDLE_TIMEOUT_MS of time.
- * Only used when WEAR_AUTO_CONN_PARAM_UPDATE is enabled.
- */
-#ifndef WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS
-#define WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS  72
-#endif
-
-/*
- * Disable the use of local GATT cache.  This forces service discovery on connection
- * establishment.
- */
-#ifndef WEAR_DISABLE_GATT_CACHE
-#define WEAR_DISABLE_GATT_CACHE               TRUE
+#define WEAR_LE_IO_CAP_OVERRIDE FALSE
 #endif
 
 #endif /* BT_TARGET_H */
index 109042f..df0e0ef 100644 (file)
@@ -79,7 +79,8 @@ EXPORT_SYMBOL const module_t stack_config_module = {
 // Interface functions
 
 static const char *get_btsnoop_log_path(void) {
-  return config_get_string(config, CONFIG_DEFAULT_SECTION, BTSNOOP_LOG_PATH_KEY, "/data/misc/bluedroid/btsnoop_hci.log");
+  return config_get_string(config, CONFIG_DEFAULT_SECTION, BTSNOOP_LOG_PATH_KEY,
+      "/data/misc/bluetooth/logs/btsnoop_hci.log");
 }
 
 static bool get_btsnoop_turned_on(void) {
index 4d372ec..d1937d1 100644 (file)
@@ -67,7 +67,9 @@ btosiCommonTestSrc := \
     ./test/future_test.cpp \
     ./test/hash_map_test.cpp \
     ./test/hash_map_utils_test.cpp \
+    ./test/leaky_bonded_queue_test.cpp \
     ./test/list_test.cpp \
+    ./test/metrics_test.cpp \
     ./test/properties_test.cpp \
     ./test/rand_test.cpp \
     ./test/reactor_test.cpp \
@@ -78,6 +80,7 @@ btosiCommonTestSrc := \
 
 btosiCommonIncludes := \
     $(LOCAL_PATH)/.. \
+    $(LOCAL_PATH)/../include \
     $(LOCAL_PATH)/../utils/include \
     $(LOCAL_PATH)/../stack/include \
     $(bluetooth_C_INCLUDES)
@@ -166,7 +169,7 @@ LOCAL_SRC_FILES := $(btosiCommonTestSrc)
 LOCAL_MODULE := net_test_osi
 LOCAL_MODULE_TAGS := tests
 LOCAL_SHARED_LIBRARIES := libc liblog libprotobuf-cpp-full libchrome libcutils
-LOCAL_STATIC_LIBRARIES := libosi libbt-protos
+LOCAL_STATIC_LIBRARIES := libosi libbt-protos libgmock
 
 LOCAL_CFLAGS += $(bluetooth_CFLAGS)
 LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
@@ -184,7 +187,7 @@ LOCAL_LDLIBS := -lrt -lpthread
 LOCAL_MODULE := net_test_osi
 LOCAL_MODULE_TAGS := tests
 LOCAL_SHARED_LIBRARIES := liblog libprotobuf-cpp-full libchrome
-LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos
+LOCAL_STATIC_LIBRARIES := libosi-host libbt-protos libgmock_host
 
 LOCAL_CFLAGS += $(bluetooth_CFLAGS) -DOS_GENERIC
 LOCAL_CONLYFLAGS += $(bluetooth_CONLYFLAGS)
index ed91fb1..80d7d3b 100644 (file)
@@ -71,7 +71,9 @@ executable("net_test_osi") {
     "test/future_test.cpp",
     "test/hash_map_test.cpp",
     "test/hash_map_utils_test.cpp",
+    "test/leaky_bonded_queue_test.cpp",
     "test/list_test.cpp",
+    "test/metrics_test.cpp",
     "test/properties_test.cpp",
     "test/rand_test.cpp",
     "test/reactor_test.cpp",
@@ -88,6 +90,8 @@ executable("net_test_osi") {
   deps = [
     "//osi",
     "//third_party/googletest:gtest_main",
+    "//third_party/googletest:gmock_main",
+    "//third_party/libchrome:base",
   ]
 
   libs = [
diff --git a/osi/include/leaky_bonded_queue.h b/osi/include/leaky_bonded_queue.h
new file mode 100644 (file)
index 0000000..8259cdc
--- /dev/null
@@ -0,0 +1,158 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2016 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <memory>
+#include <mutex>
+#include <queue>
+
+namespace system_bt_osi {
+
+/*
+ *   LeakyBondedQueue<T>
+ *
+ * - LeakyLondedQueue<T> is a fixed size queue that leaks oldest item when
+ *   reaching its capacity. This is useful in creating memory bonded data
+ *   structure where freshness is more important than full coverage.
+ * - The queue is protected by a simple mutex and is thread-safe, although
+ *   improvements could be made to lock enqueue and dequeue separately, it
+ *   is not implemented at this moment due to lack of demand
+ * - The queue uses unique_ptr to automatically free its content when it is
+ *   destructed. It is the user's responsibility to implement T's destructor
+ *   correctly.
+ *
+ */
+template <class T>
+class LeakyBondedQueue {
+ public:
+  LeakyBondedQueue(size_t capacity);
+  /* Default destructor
+   *
+   * Call Clear() and free the queue structure itself
+   */
+  ~LeakyBondedQueue();
+  /*
+   * Add item NEW_ITEM to the underlining queue. If the queue is full, pop
+   * the oldest item
+   */
+  void Enqueue(T* new_item);
+  /*
+   * Add item NEW_ITEM to the underlining queue. If the queue is full, dequeue
+   * the oldest item and returns it to the caller. Return nullptr otherwise.
+   */
+  T* EnqueueWithPop(T* new_item);
+  /*
+   * Dequeues the oldest item from the queue. Return nullptr if queue is empty
+   */
+  T* Dequeue();
+  /*
+   * Returns the length of queue
+   */
+  size_t Length();
+  /*
+   * Returns the defined capacity of the queue
+   */
+  size_t Capacity();
+  /*
+   * Returns whether the queue is empty
+   */
+  bool Empty();
+  /*
+   * Pops all items from the queue
+   */
+  void Clear();
+
+ private:
+  // Put item in unique_ptr so that they get freed automatically when poped or
+  // when queue_ is freed
+  std::queue<std::unique_ptr<T>> queue_;
+  std::mutex lock_;
+  size_t capacity_;
+};
+
+/*
+* Definitions must be in the header for template classes
+*/
+
+template <class T>
+LeakyBondedQueue<T>::LeakyBondedQueue(size_t capacity) {
+  capacity_ = capacity;
+}
+
+template <class T>
+LeakyBondedQueue<T>::~LeakyBondedQueue() {}
+
+template <class T>
+void LeakyBondedQueue<T>::Enqueue(T* new_item) {
+  std::lock_guard<std::mutex> lock(lock_);
+  if ((queue_.size() + 1) > capacity_) {
+    queue_.pop();
+  }
+  std::unique_ptr<T> item_ptr(new_item);
+  queue_.push(std::move(item_ptr));
+}
+
+template <class T>
+T* LeakyBondedQueue<T>::EnqueueWithPop(T* new_item) {
+  std::lock_guard<std::mutex> lock(lock_);
+  T* old_item = nullptr;
+  if ((queue_.size() + 1) > capacity_) {
+    std::unique_ptr<T> item = std::move(queue_.front());
+    queue_.pop();
+    old_item = item.release();
+  }
+  std::unique_ptr<T> item_ptr(new_item);
+  queue_.push(std::move(item_ptr));
+  return old_item;
+}
+
+template <class T>
+T* LeakyBondedQueue<T>::Dequeue() {
+  std::lock_guard<std::mutex> lock(lock_);
+  std::unique_ptr<T> item = std::move(queue_.front());
+  queue_.pop();
+  return item.release();
+}
+
+template <class T>
+void LeakyBondedQueue<T>::Clear() {
+  std::lock_guard<std::mutex> lock(lock_);
+  while (!queue_.empty()) {
+    // unique_ptr does not need to be freed
+    queue_.pop();
+  }
+}
+
+template <class T>
+size_t LeakyBondedQueue<T>::Length() {
+  std::lock_guard<std::mutex> lock(lock_);
+  return queue_.size();
+}
+
+template <class T>
+size_t LeakyBondedQueue<T>::Capacity() {
+  return capacity_;
+}
+
+template <class T>
+bool LeakyBondedQueue<T>::Empty() {
+  std::lock_guard<std::mutex> lock(lock_);
+  return queue_.empty();
+}
+
+}  // namespace system_bt_osi
index 4855301..4ef12b2 100644 (file)
 
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Typedefs to hide protobuf definition to the rest of stack
+
 typedef enum {
   DEVICE_TYPE_UNKNOWN,
   DEVICE_TYPE_BREDR,
@@ -27,26 +32,12 @@ typedef enum {
   DEVICE_TYPE_DUMO,
 } device_type_t;
 
-// Record a pairing event at Unix epoch time |timestamp_ms|
-// |device_class| and |device_type| denote the type of device paired.
-// |disconnect_reason| is the HCI reason for pairing disconnection,
-// see stack/include/hcidefs.h
-void metrics_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms,
-                        uint32_t device_class, device_type_t device_type);
-
 typedef enum {
   WAKE_EVENT_UNKNOWN,
   WAKE_EVENT_ACQUIRED,
   WAKE_EVENT_RELEASED,
 } wake_event_type_t;
 
-// Record a wake event at Unix epoch time |timestamp_ms|.
-// |type| specifies whether it was acquired or relased,
-// |requestor| if provided is the service requesting the wake lock.
-// |name| is the name of the wake lock held.
-void metrics_wake_event(wake_event_type_t type, const char *requestor,
-                        const char *name, uint64_t timestamp_ms);
-
 typedef enum {
   SCAN_TYPE_UNKNOWN,
   SCAN_TECH_TYPE_LE,
@@ -54,44 +45,52 @@ typedef enum {
   SCAN_TECH_TYPE_BOTH,
 } scan_tech_t;
 
-// Record a scan event at Unix epoch time |timestamp_ms|.
-// |start| is true if this is the beginning of the scan.
-// |initiator| is a unique ID identifying the app starting the scan.
-// |type| is whether the scan reports BR/EDR, LE, or both.
-// |results| is the number of results to be reported.
-void metrics_scan_event(bool start, const char *initator, scan_tech_t type,
-                        uint32_t results, uint64_t timestamp_ms);
-
-// Record A2DP session information.
-// |session_duration_sec| is the session duration (in seconds).
-// |device_class| is the device class of the paired device.
-// |media_timer_min_ms| is the minimum scheduled time (in milliseconds)
-// of the media timer.
-// |media_timer_max_ms| is the maximum scheduled time (in milliseconds)
-// of the media timer.
-// |media_timer_avg_ms| is the average scheduled time (in milliseconds)
-// of the media timer.
-// |buffer_overruns_max_count| - TODO - not clear what this is.
-// |buffer_overruns_total| is the number of times the media buffer with
-// audio data has overrun.
-// |buffer_underruns_average| - TODO - not clear what this is.
-// |buffer_underruns_count| is the number of times there was no enough
-// audio data to add to the media buffer.
-void metrics_a2dp_session(int64_t session_duration_sec,
-                          const char *disconnect_reason,
-                          uint32_t device_class,
-                          int32_t media_timer_min_ms,
-                          int32_t media_timer_max_ms,
-                          int32_t media_timer_avg_ms,
-                          int32_t buffer_overruns_max_count,
-                          int32_t buffer_overruns_total,
-                          float buffer_underruns_average,
-                          int32_t buffer_underruns_count);
-
-// Writes the metrics, in packed protobuf format, into the descriptor |fd|.
-// If |clear| is true, metrics events are cleared afterwards.
-void metrics_write(int fd, bool clear);
-
-// Writes the metrics, in human-readable protobuf format, into the descriptor
-// |fd|. If |clear| is true, metrics events are cleared afterwards.
-void metrics_print(int fd, bool clear);
+typedef enum {
+  CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
+  CONNECTION_TECHNOLOGY_TYPE_LE,
+  CONNECTION_TECHNOLOGY_TYPE_BREDR,
+} connection_tech_t;
+
+typedef enum {
+  DISCONNECT_REASON_UNKNOWN,
+  DISCONNECT_REASON_METRICS_DUMP,
+  DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
+} disconnect_reason_t;
+
+typedef struct {
+  int64_t audio_duration_ms;
+  int32_t media_timer_min_ms;
+  int32_t media_timer_max_ms;
+  int32_t media_timer_avg_ms;
+  int64_t total_scheduling_count;
+  int32_t buffer_overruns_max_count;
+  int32_t buffer_overruns_total;
+  float buffer_underruns_average;
+  int32_t buffer_underruns_count;
+} A2dpSessionMetrics_t;
+
+void metrics_log_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms,
+                    uint32_t device_class, device_type_t device_type);
+
+void metrics_log_wake_event(wake_event_type_t type, const char* requestor,
+                    const char* name, uint64_t timestamp_ms);
+
+void metrics_log_scan_event(bool start, const char* initator, scan_tech_t type,
+                    uint32_t results, uint64_t timestamp_ms);
+
+void metrics_log_bluetooth_session_start(connection_tech_t connection_tech_type,
+                                uint64_t timestamp_ms);
+
+void metrics_log_bluetooth_session_end(disconnect_reason_t disconnect_reason,
+  uint64_t timestamp_ms);
+
+void metrics_log_bluetooth_session_device_info(uint32_t device_class,
+                                     device_type_t device_type);
+
+void metrics_log_a2dp_session(A2dpSessionMetrics_t* metrics);
+
+void metrics_write_base64(int fd, bool clear);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/osi/include/metrics_cpp.h b/osi/include/metrics_cpp.h
new file mode 100644 (file)
index 0000000..dcba21c
--- /dev/null
@@ -0,0 +1,230 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2016 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+#include <stdint.h>
+#include <memory>
+#include <string>
+
+namespace system_bt_osi {
+
+/* Values of A2DP metrics that we care about
+ *
+ *    audio_duration_ms : sum of audio duration (in milliseconds).
+ *    device_class: device class of the paired device.
+ *    media_timer_min_ms : minimum scheduled time (in milliseconds)
+ *                         of the media timer.
+ *    media_timer_max_ms: maximum scheduled time (in milliseconds)
+ *                        of the media timer.
+ *    media_timer_avg_ms: average scheduled time (in milliseconds)
+ *                        of the media timer.
+ *    buffer_overruns_max_count: TODO - not clear what this is.
+ *    buffer_overruns_total : number of times the media buffer with
+ *                            audio data has overrun
+ *    buffer_underruns_average: TODO - not clear what this is.
+ *    buffer_underruns_count: number of times there was no enough
+ *                            audio data to add to the media buffer.
+ * NOTE: Negative values are invalid
+*/
+class A2dpSessionMetrics {
+ public:
+  A2dpSessionMetrics() {}
+
+  /*
+   * Update the metrics value in the current metrics object using the metrics
+   * objects supplied
+   */
+  void Update(const A2dpSessionMetrics& metrics);
+
+  /*
+   * Compare whether two metrics objects are equal
+   */
+  bool operator==(const A2dpSessionMetrics& rhs) const;
+
+  /*
+   * Initialize all values to -1 which is invalid in order to make a distinction
+   * between 0 and invalid values
+   */
+  int64_t audio_duration_ms = -1;
+  int32_t media_timer_min_ms = -1;
+  int32_t media_timer_max_ms = -1;
+  int32_t media_timer_avg_ms = -1;
+  int64_t total_scheduling_count = -1;
+  int32_t buffer_overruns_max_count = -1;
+  int32_t buffer_overruns_total = -1;
+  float buffer_underruns_average = -1;
+  int32_t buffer_underruns_count = -1;
+};
+
+class BluetoothMetricsLogger {
+ public:
+  static BluetoothMetricsLogger* GetInstance() {
+    static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger();
+    return instance;
+  }
+
+  /*
+   * Record a pairing event
+   *
+   * Parameters:
+   *    timestamp_ms: Unix epoch time in milliseconds
+   *    device_class: class of remote device
+   *    device_type: type of remote device
+   *    disconnect_reason: HCI reason for pairing disconnection.
+   *                       See: stack/include/hcidefs.h
+   */
+  void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms,
+                    uint32_t device_class, device_type_t device_type);
+
+  /*
+   * Record a wake event
+   *
+   * Parameters:
+   *    timestamp_ms: Unix epoch time in milliseconds
+   *    type: whether it was acquired or released
+   *    requestor: if provided is the service requesting the wake lock
+   *    name: the name of the wake lock held
+   */
+  void LogWakeEvent(wake_event_type_t type, const std::string& requestor,
+                    const std::string& name, uint64_t timestamp_ms);
+
+  /*
+   * Record a scan event
+   *
+   * Parameters
+   *    timestamp_ms : Unix epoch time in milliseconds
+   *    start : true if this is the beginning of the scan
+   *    initiator: a unique ID identifying the app starting the scan
+   *    type: whether the scan reports BR/EDR, LE, or both.
+   *    results: number of results to be reported.
+   */
+  void LogScanEvent(bool start, const std::string& initator, scan_tech_t type,
+                    uint32_t results, uint64_t timestamp_ms);
+
+  /*
+   * Start logging a Bluetooth session
+   *
+   * A Bluetooth session is defined a a connection between this device and
+   * another remote device which may include multiple profiles and protocols
+   *
+   * Only one Bluetooth session can exist at one time. Calling this method twice
+   * without LogBluetoothSessionEnd will result in logging a premature end of
+   * current Bluetooth session
+   *
+   * Parameters:
+   *    connection_tech_type : type of connection technology
+   *    timestamp_ms : the timestamp for session start, 0 means now
+   *
+   */
+  void LogBluetoothSessionStart(connection_tech_t connection_tech_type,
+                                uint64_t timestamp_ms);
+
+  /*
+   * Stop logging a Bluetooth session and pushes it to the log queue
+   *
+   * If no Bluetooth session exist, this method exits immediately
+   *
+   * Parameters:
+   *    disconnect_reason : A string representation of disconnect reason
+   *    timestamp_ms : the timestamp of session end, 0 means now
+   *
+   */
+  void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
+                              uint64_t timestamp_ms);
+
+  /*
+   * Log information about remote device in a current Bluetooth session
+   *
+   * If a Bluetooth session does not exist, create one with default parameter
+   * and timestamp now
+   *
+   * Parameters:
+   *    device_class : device_class defined in btm_api_types.h
+   *    device_type : type of remote device
+   */
+  void LogBluetoothSessionDeviceInfo(uint32_t device_class,
+                                     device_type_t device_type);
+
+  /*
+   * Log A2DP Audio Session Information
+   *
+   * - Repeated calls to this method will override previous metrics if in the
+   *   same Bluetooth connection
+   * - If a Bluetooth session does not exist, create one with default parameter
+   *   and timestamp now
+   *
+   * Parameters:
+   *    a2dp_session_metrics - pointer to struct holding a2dp stats
+   *
+   */
+  void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
+
+  /*
+   * Writes the metrics, in base64 protobuf format, into the descriptor FD
+   * If CLEAR is true, metrics events are cleared afterwards.
+   */
+  void WriteBase64(int fd, bool clear);
+  void WriteBase64String(std::string* serialized, bool clear);
+  void WriteString(std::string* serialized, bool clear);
+
+  /*
+   * Reset the metrics logger by cleaning up its staging queues and existing
+   * protobuf objects.
+   */
+  void Reset();
+
+  /*
+   * Maximum number of log entries for each session or event
+   */
+  static const size_t kMaxNumBluetoothSession = 50;
+  static const size_t kMaxNumPairEvent = 50;
+  static const size_t kMaxNumWakeEvent = 1000;
+  static const size_t kMaxNumScanEvent = 50;
+
+ private:
+  BluetoothMetricsLogger();
+
+  /*
+   * When a Bluetooth session is on and the user initiates a metrics dump, we
+   * need to be able to upload whatever we have first. This method breaks the
+   * ongoing Bluetooth session into two sessions with the previous one labeled
+   * as "METRICS_DUMP" for the disconnect reason.
+   */
+  void CutoffSession();
+
+  /*
+   * Build the internal metrics object using information gathered
+   */
+  void Build();
+
+  /*
+   * Reset objects related to current Bluetooth session
+   */
+  void ResetSession();
+
+  /*
+   * Reset the underlining BluetoothLog object
+   */
+  void ResetLog();
+
+  /*
+   * PIMPL style implementation to hide internal dependencies
+   */
+  struct impl;
+  std::unique_ptr<impl> const pimpl_;
+};
+
+} // namespace system_bt_osi
index 064f99e..9a91983 100644 (file)
  *  limitations under the License.
  *
  ******************************************************************************/
-
-
 #define LOG_TAG "bt_osi_metrics"
 
-extern "C" {
-#include "osi/include/metrics.h"
+#include <unistd.h>
+#include <algorithm>
+#include <cerrno>
+#include <chrono>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <mutex>
 
-#include <errno.h>
+#include <base/base64.h>
+#include <base/logging.h>
 
+#include "osi/include/leaky_bonded_queue.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-}
+#include "stack/include/btm_api.h"
 
 #include "osi/src/protos/bluetooth.pb.h"
 
-#include <base/base64.h>
-#include <google/protobuf/text_format.h>
-#include <mutex>
+#include "osi/include/metrics.h"
+#include "osi/include/metrics_cpp.h"
+
+namespace system_bt_osi {
 
 using clearcut::connectivity::A2DPSession;
 using clearcut::connectivity::BluetoothLog;
 using clearcut::connectivity::BluetoothSession;
+using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType;
+using clearcut::connectivity::BluetoothSession_DisconnectReasonType;
 using clearcut::connectivity::DeviceInfo;
 using clearcut::connectivity::DeviceInfo_DeviceType;
 using clearcut::connectivity::PairEvent;
@@ -46,156 +55,378 @@ using clearcut::connectivity::ScanEvent_ScanEventType;
 using clearcut::connectivity::WakeEvent;
 using clearcut::connectivity::WakeEvent_WakeEventType;
 
-BluetoothLog *pending;
-std::mutex log_lock;
+uint64_t metrics_time_get_os_boottime_us(void) {
+  struct timespec ts_now;
+  clock_gettime(CLOCK_BOOTTIME, &ts_now);
 
-static void lazy_initialize(void) {
-  if (pending == nullptr) {
-    pending = BluetoothLog::default_instance().New();
-  }
+  return ((uint64_t)ts_now.tv_sec * 1000000L) +
+         ((uint64_t)ts_now.tv_nsec / 1000);
 }
 
-void metrics_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms,
-                        uint32_t device_class, device_type_t device_type) {
-  std::lock_guard<std::mutex> lock(log_lock);
-  lazy_initialize();
-
-  PairEvent *event = pending->add_pair_event();
-
-  DeviceInfo *info = event->mutable_device_paired_with();
-
-  info->set_device_class(device_class);
-
-  DeviceInfo_DeviceType type = DeviceInfo::DEVICE_TYPE_UNKNOWN;
-
-  if (device_type == DEVICE_TYPE_BREDR)
-    type = DeviceInfo::DEVICE_TYPE_BREDR;
-  if (device_type == DEVICE_TYPE_LE)
-    type = DeviceInfo::DEVICE_TYPE_LE;
-  if (device_type == DEVICE_TYPE_DUMO)
-    type = DeviceInfo::DEVICE_TYPE_DUMO;
+/*
+ * Get current OS boot time in millisecond
+ */
+static int64_t time_get_os_boottime_ms(void) {
+  return metrics_time_get_os_boottime_us() / 1000;
+}
 
-  info->set_device_type(type);
+static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
+                              int64_t ct_b) {
+  if (ct_a > 0 && ct_b > 0) {
+    return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
+  } else if (ct_b > 0) {
+    return avg_b;
+  } else {
+    return avg_a;
+  }
+}
 
-  event->set_disconnect_reason(disconnect_reason);
+static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
+                                int64_t ct_b) {
+  if (ct_a > 0 && ct_b > 0) {
+    return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
+  } else if (ct_b > 0) {
+    return avg_b;
+  } else {
+    return avg_a;
+  }
+}
 
-  event->set_event_time_millis(timestamp_ms);
+void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
+  if (metrics.audio_duration_ms >= 0) {
+    audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
+    audio_duration_ms += metrics.audio_duration_ms;
+  }
+  if (metrics.media_timer_min_ms >= 0) {
+    if (media_timer_min_ms < 0) {
+      media_timer_min_ms = metrics.media_timer_min_ms;
+    } else {
+      media_timer_min_ms =
+          std::min(media_timer_min_ms, metrics.media_timer_min_ms);
+    }
+  }
+  if (metrics.media_timer_max_ms >= 0) {
+    media_timer_max_ms =
+        std::max(media_timer_max_ms, metrics.media_timer_max_ms);
+  }
+  if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) {
+    if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
+      media_timer_avg_ms = metrics.media_timer_avg_ms;
+      total_scheduling_count = metrics.total_scheduling_count;
+    } else {
+      media_timer_avg_ms = combine_averages(
+          media_timer_avg_ms, total_scheduling_count,
+          metrics.media_timer_avg_ms, metrics.total_scheduling_count);
+      total_scheduling_count += metrics.total_scheduling_count;
+    }
+  }
+  if (metrics.buffer_overruns_max_count >= 0) {
+    buffer_overruns_max_count =
+        std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
+  }
+  if (metrics.buffer_overruns_total >= 0) {
+    buffer_overruns_total =
+        std::max(static_cast<int32_t>(0), buffer_overruns_total);
+    buffer_overruns_total += metrics.buffer_overruns_total;
+  }
+  if (metrics.buffer_underruns_average >= 0 &&
+      metrics.buffer_underruns_count >= 0) {
+    if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
+      buffer_underruns_average = metrics.buffer_underruns_average;
+      buffer_underruns_count = metrics.buffer_underruns_count;
+    } else {
+      buffer_underruns_average = combine_averages(
+          buffer_underruns_average, buffer_underruns_count,
+          metrics.buffer_underruns_average, metrics.buffer_underruns_count);
+      buffer_underruns_count += metrics.buffer_underruns_count;
+    }
+  }
 }
 
-void metrics_wake_event(wake_event_type_t type, const char *requestor,
-                        const char *name, uint64_t timestamp_ms) {
-  std::lock_guard<std::mutex> lock(log_lock);
-  lazy_initialize();
+bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
+  return audio_duration_ms == rhs.audio_duration_ms &&
+         media_timer_min_ms == rhs.media_timer_min_ms &&
+         media_timer_max_ms == rhs.media_timer_max_ms &&
+         media_timer_avg_ms == rhs.media_timer_avg_ms &&
+         total_scheduling_count == rhs.total_scheduling_count &&
+         buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
+         buffer_overruns_total == rhs.buffer_overruns_total &&
+         buffer_underruns_average == rhs.buffer_underruns_average &&
+         buffer_underruns_count == rhs.buffer_underruns_count;
+}
 
-  WakeEvent *event = pending->add_wake_event();
+static DeviceInfo_DeviceType get_device_type(device_type_t type) {
+  switch (type) {
+    case DEVICE_TYPE_BREDR:
+      return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR;
+    case DEVICE_TYPE_LE:
+      return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE;
+    case DEVICE_TYPE_DUMO:
+      return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO;
+    case DEVICE_TYPE_UNKNOWN:
+    default:
+      return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN;
+  }
+}
 
-  WakeEvent_WakeEventType waketype = WakeEvent::UNKNOWN;
+static BluetoothSession_ConnectionTechnologyType get_connection_tech_type(
+    connection_tech_t type) {
+  switch (type) {
+    case CONNECTION_TECHNOLOGY_TYPE_LE:
+      return BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE;
+    case CONNECTION_TECHNOLOGY_TYPE_BREDR:
+      return BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR;
+    case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN:
+    default:
+      return BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN;
+  }
+}
 
-  if (type == WAKE_EVENT_ACQUIRED)
-    waketype = WakeEvent::ACQUIRED;
-  if (type == WAKE_EVENT_RELEASED)
-    waketype = WakeEvent::RELEASED;
+static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) {
+  switch (type) {
+    case SCAN_TECH_TYPE_LE:
+      return ScanEvent_ScanTechnologyType::
+          ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE;
+    case SCAN_TECH_TYPE_BREDR:
+      return ScanEvent_ScanTechnologyType::
+          ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR;
+    case SCAN_TECH_TYPE_BOTH:
+      return ScanEvent_ScanTechnologyType::
+          ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH;
+    case SCAN_TYPE_UNKNOWN:
+    default:
+      return ScanEvent_ScanTechnologyType::
+          ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN;
+  }
+}
 
-  event->set_wake_event_type(waketype);
+static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) {
+  switch (type) {
+    case WAKE_EVENT_ACQUIRED:
+      return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED;
+    case WAKE_EVENT_RELEASED:
+      return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED;
+    case WAKE_EVENT_UNKNOWN:
+    default:
+      return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN;
+  }
+}
 
-  if (requestor)
-    event->set_requestor(requestor);
+static BluetoothSession_DisconnectReasonType get_disconnect_reason_type(
+  disconnect_reason_t type) {
+  switch (type) {
+    case DISCONNECT_REASON_METRICS_DUMP:
+      return BluetoothSession_DisconnectReasonType::
+        BluetoothSession_DisconnectReasonType_METRICS_DUMP;
+    case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS:
+      return BluetoothSession_DisconnectReasonType::
+        BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS;
+    case DISCONNECT_REASON_UNKNOWN:
+    default:
+      return BluetoothSession_DisconnectReasonType::
+        BluetoothSession_DisconnectReasonType_UNKNOWN;
+  }
+}
 
-  if (name)
-    event->set_name(name);
+struct BluetoothMetricsLogger::impl {
+  impl(size_t max_bluetooth_session, size_t max_pair_event,
+       size_t max_wake_event, size_t max_scan_event)
+      : bt_session_queue_(
+            new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)),
+        pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)),
+        wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
+        scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
+    bluetooth_log_ = BluetoothLog::default_instance().New();
+    bluetooth_session_ = nullptr;
+    bluetooth_session_start_time_ms_ = 0;
+    a2dp_session_metrics_ = A2dpSessionMetrics();
+  }
 
+  /* Bluetooth log lock protected */
+  BluetoothLog* bluetooth_log_;
+  std::recursive_mutex bluetooth_log_lock_;
+  /* End Bluetooth log lock protected */
+  /* Bluetooth session lock protected */
+  BluetoothSession* bluetooth_session_;
+  uint64_t bluetooth_session_start_time_ms_;
+  A2dpSessionMetrics a2dp_session_metrics_;
+  std::recursive_mutex bluetooth_session_lock_;
+  /* End bluetooth session lock protected */
+  std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_;
+  std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_;
+  std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_;
+  std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_;
+};
+
+BluetoothMetricsLogger::BluetoothMetricsLogger()
+    : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent,
+                      kMaxNumWakeEvent, kMaxNumScanEvent)) {}
+
+void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
+                                          uint64_t timestamp_ms,
+                                          uint32_t device_class,
+                                          device_type_t device_type) {
+  PairEvent* event = new PairEvent();
+  DeviceInfo* info = event->mutable_device_paired_with();
+  info->set_device_class(device_class);
+  info->set_device_type(get_device_type(device_type));
+  event->set_disconnect_reason(disconnect_reason);
   event->set_event_time_millis(timestamp_ms);
+  pimpl_->pair_event_queue_->Enqueue(event);
+  {
+    std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+    pimpl_->bluetooth_log_->set_num_pair_event(
+        pimpl_->bluetooth_log_->num_pair_event() + 1);
+  }
 }
 
-void metrics_scan_event(bool start, const char *initator, scan_tech_t type,
-                        uint32_t results, uint64_t timestamp_ms) {
-  std::lock_guard<std::mutex> lock(log_lock);
-  lazy_initialize();
-
-  ScanEvent *event = pending->add_scan_event();
+void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
+                                          const std::string& requestor,
+                                          const std::string& name,
+                                          uint64_t timestamp_ms) {
+  WakeEvent* event = new WakeEvent();
+  event->set_wake_event_type(get_wake_event_type(type));
+  event->set_requestor(requestor);
+  event->set_name(name);
+  event->set_event_time_millis(timestamp_ms);
+  pimpl_->wake_event_queue_->Enqueue(event);
+  {
+    std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+    pimpl_->bluetooth_log_->set_num_wake_event(
+        pimpl_->bluetooth_log_->num_wake_event() + 1);
+  }
+}
 
-  if (start)
+void BluetoothMetricsLogger::LogScanEvent(bool start,
+                                          const std::string& initator,
+                                          scan_tech_t type, uint32_t results,
+                                          uint64_t timestamp_ms) {
+  ScanEvent* event = new ScanEvent();
+  if (start) {
     event->set_scan_event_type(ScanEvent::SCAN_EVENT_START);
-  else
+  } else {
     event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP);
-
-  if (initator)
-    event->set_initiator(initator);
-
-  ScanEvent::ScanTechnologyType scantype = ScanEvent::SCAN_TYPE_UNKNOWN;
-
-  if (type == SCAN_TECH_TYPE_LE)
-    scantype = ScanEvent::SCAN_TECH_TYPE_LE;
-  if (type == SCAN_TECH_TYPE_BREDR)
-    scantype = ScanEvent::SCAN_TECH_TYPE_BREDR;
-  if (type == SCAN_TECH_TYPE_BOTH)
-    scantype = ScanEvent::SCAN_TECH_TYPE_BOTH;
-
-  event->set_scan_technology_type(scantype);
-
+  }
+  event->set_initiator(initator);
+  event->set_scan_technology_type(get_scan_tech_type(type));
   event->set_number_results(results);
-
   event->set_event_time_millis(timestamp_ms);
+  pimpl_->scan_event_queue_->Enqueue(event);
+  {
+    std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+    pimpl_->bluetooth_log_->set_num_scan_event(
+        pimpl_->bluetooth_log_->num_scan_event() + 1);
+  }
+}
+
+void BluetoothMetricsLogger::LogBluetoothSessionStart(
+    connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
+  if (pimpl_->bluetooth_session_ != nullptr) {
+    LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
+      0);
+  }
+  if (timestamp_ms == 0) {
+    timestamp_ms = time_get_os_boottime_ms();
+  }
+  pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms;
+  pimpl_->bluetooth_session_ = new BluetoothSession();
+  pimpl_->bluetooth_session_->set_connection_technology_type(
+      get_connection_tech_type(connection_tech_type));
+}
+
+void BluetoothMetricsLogger::LogBluetoothSessionEnd(
+    disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
+  if (pimpl_->bluetooth_session_ == nullptr) {
+    return;
+  }
+  if (timestamp_ms == 0) {
+    timestamp_ms = time_get_os_boottime_ms();
+  }
+  int64_t session_duration_sec =
+      (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000;
+  pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec);
+  pimpl_->bluetooth_session_->set_disconnect_reason_type(
+    get_disconnect_reason_type(disconnect_reason));
+  pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_);
+  pimpl_->bluetooth_session_ = nullptr;
+  {
+    std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_);
+    pimpl_->bluetooth_log_->set_num_bluetooth_session(
+        pimpl_->bluetooth_log_->num_bluetooth_session() + 1);
+  }
 }
 
-void metrics_a2dp_session(int64_t session_duration_sec,
-                          const char *disconnect_reason,
-                          uint32_t device_class,
-                          int32_t media_timer_min_ms,
-                          int32_t media_timer_max_ms,
-                          int32_t media_timer_avg_ms,
-                          int32_t buffer_overruns_max_count,
-                          int32_t buffer_overruns_total,
-                          float buffer_underruns_average,
-                          int32_t buffer_underruns_count) {
-  std::lock_guard<std::mutex> lock(log_lock);
-  lazy_initialize();
-
-  BluetoothSession *bt_session = pending->add_session();
-
-  // Set connection type: for A2DP it is always BR/EDR
-  BluetoothSession::ConnectionTechnologyType conn_type =
-    BluetoothSession::CONNECTION_TECHNOLOGY_TYPE_BREDR;
-  bt_session->set_connection_technology_type(conn_type);
-
-  bt_session->set_session_duration_sec(session_duration_sec);
-  if (disconnect_reason != NULL)
-    bt_session->set_disconnect_reason(disconnect_reason);
-
-  // Set device: class and type are pre-defined
-  DeviceInfo *info = bt_session->mutable_device_connected_to();
+void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
+    uint32_t device_class, device_type_t device_type) {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
+  if (pimpl_->bluetooth_session_ == nullptr) {
+    LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
+  }
+  DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to();
   info->set_device_class(device_class);
   info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR);
+}
 
-  A2DPSession *a2dp_session = bt_session->mutable_a2dp_session();
-  a2dp_session->set_media_timer_min_millis(media_timer_min_ms);
-  a2dp_session->set_media_timer_max_millis(media_timer_max_ms);
-  a2dp_session->set_media_timer_avg_millis(media_timer_avg_ms);
-  a2dp_session->set_buffer_overruns_max_count(buffer_overruns_max_count);
-  a2dp_session->set_buffer_overruns_total(buffer_overruns_total);
-  a2dp_session->set_buffer_underruns_average(buffer_underruns_average);
-  a2dp_session->set_buffer_underruns_count(buffer_underruns_count);
+void BluetoothMetricsLogger::LogA2dpSession(
+    const A2dpSessionMetrics& a2dp_session_metrics) {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
+  if (pimpl_->bluetooth_session_ == nullptr) {
+    // When no bluetooth session exist, create one on system's behalf
+    // Set connection type: for A2DP it is always BR/EDR
+    LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+    LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR);
+  }
+  // Accumulate metrics
+  pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics);
+  // Get or allocate new A2DP session object
+  A2DPSession* a2dp_session =
+      pimpl_->bluetooth_session_->mutable_a2dp_session();
+  a2dp_session->set_audio_duration_millis(
+      pimpl_->a2dp_session_metrics_.audio_duration_ms);
+  a2dp_session->set_media_timer_min_millis(
+      pimpl_->a2dp_session_metrics_.media_timer_min_ms);
+  a2dp_session->set_media_timer_max_millis(
+      pimpl_->a2dp_session_metrics_.media_timer_max_ms);
+  a2dp_session->set_media_timer_avg_millis(
+      pimpl_->a2dp_session_metrics_.media_timer_avg_ms);
+  a2dp_session->set_buffer_overruns_max_count(
+      pimpl_->a2dp_session_metrics_.buffer_overruns_max_count);
+  a2dp_session->set_buffer_overruns_total(
+      pimpl_->a2dp_session_metrics_.buffer_overruns_total);
+  a2dp_session->set_buffer_underruns_average(
+      pimpl_->a2dp_session_metrics_.buffer_underruns_average);
+  a2dp_session->set_buffer_underruns_count(
+      pimpl_->a2dp_session_metrics_.buffer_underruns_count);
 }
 
-void metrics_write(int fd, bool clear) {
-  log_lock.lock();
+void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+  LOG_DEBUG(LOG_TAG, "%s building metrics", __func__);
+  Build();
   LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__);
-  lazy_initialize();
-
-  std::string serialized;
-  if (!pending->SerializeToString(&serialized)) {
+  if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
     LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__);
     return;
   }
-
   if (clear) {
-    pending->Clear();
+    pimpl_->bluetooth_log_->Clear();
   }
-  log_lock.unlock();
+}
 
-  std::string protoBase64;
-  base::Base64Encode(serialized, &protoBase64);
+void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
+                                               bool clear) {
+  this->WriteString(serialized, clear);
+  base::Base64Encode(*serialized, serialized);
+}
 
+void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
+  std::string protoBase64;
+  this->WriteBase64String(&protoBase64, clear);
   ssize_t ret;
   OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
   if (ret == -1) {
@@ -204,23 +435,137 @@ void metrics_write(int fd, bool clear) {
   }
 }
 
-void metrics_print(int fd, bool clear) {
-  log_lock.lock();
-  LOG_DEBUG(LOG_TAG, "%s printing metrics", __func__);
-  lazy_initialize();
-
-  std::string pretty_output;
-  google::protobuf::TextFormat::PrintToString(*pending, &pretty_output);
+void BluetoothMetricsLogger::CutoffSession() {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
+  if (pimpl_->bluetooth_session_ != nullptr) {
+    BluetoothSession* new_bt_session =
+        new BluetoothSession(*pimpl_->bluetooth_session_);
+    new_bt_session->clear_a2dp_session();
+    new_bt_session->clear_rfcomm_session();
+    LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0);
+    pimpl_->bluetooth_session_ = new_bt_session;
+    pimpl_->bluetooth_session_start_time_ms_ = time_get_os_boottime_ms();
+    pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
+  }
+}
 
-  if (clear) {
-    pending->Clear();
+void BluetoothMetricsLogger::Build() {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+  CutoffSession();
+  BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_;
+  while (!pimpl_->bt_session_queue_->Empty() &&
+         static_cast<size_t>(bluetooth_log->session_size()) <=
+             pimpl_->bt_session_queue_->Capacity()) {
+    bluetooth_log->mutable_session()->AddAllocated(
+        pimpl_->bt_session_queue_->Dequeue());
+  }
+  while (!pimpl_->pair_event_queue_->Empty() &&
+         static_cast<size_t>(bluetooth_log->pair_event_size()) <=
+             pimpl_->pair_event_queue_->Capacity()) {
+    bluetooth_log->mutable_pair_event()->AddAllocated(
+        pimpl_->pair_event_queue_->Dequeue());
+  }
+  while (!pimpl_->scan_event_queue_->Empty() &&
+         static_cast<size_t>(bluetooth_log->scan_event_size()) <=
+             pimpl_->scan_event_queue_->Capacity()) {
+    bluetooth_log->mutable_scan_event()->AddAllocated(
+        pimpl_->scan_event_queue_->Dequeue());
+  }
+  while (!pimpl_->wake_event_queue_->Empty() &&
+         static_cast<size_t>(bluetooth_log->wake_event_size()) <=
+             pimpl_->wake_event_queue_->Capacity()) {
+    bluetooth_log->mutable_wake_event()->AddAllocated(
+        pimpl_->wake_event_queue_->Dequeue());
   }
-  log_lock.unlock();
+  while (!pimpl_->bt_session_queue_->Empty() &&
+         static_cast<size_t>(bluetooth_log->wake_event_size()) <=
+             pimpl_->wake_event_queue_->Capacity()) {
+    bluetooth_log->mutable_wake_event()->AddAllocated(
+        pimpl_->wake_event_queue_->Dequeue());
+  }
+}
 
-  ssize_t ret;
-  OSI_NO_INTR(ret = write(fd, pretty_output.c_str(), pretty_output.size()));
-  if (ret == -1) {
-    LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__,
-              strerror(errno), errno);
+void BluetoothMetricsLogger::ResetSession() {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
+  if (pimpl_->bluetooth_session_ != nullptr) {
+    delete pimpl_->bluetooth_session_;
+    pimpl_->bluetooth_session_ = nullptr;
   }
+  pimpl_->bluetooth_session_start_time_ms_ = 0;
+  pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
+}
+
+void BluetoothMetricsLogger::ResetLog() {
+  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
+  pimpl_->bluetooth_log_->Clear();
+}
+
+void BluetoothMetricsLogger::Reset() {
+  ResetSession();
+  ResetLog();
+  pimpl_->bt_session_queue_->Clear();
+  pimpl_->pair_event_queue_->Clear();
+  pimpl_->wake_event_queue_->Clear();
+  pimpl_->scan_event_queue_->Clear();
+}
+
+}  // namespace system_bt_osi
+
+using system_bt_osi::BluetoothMetricsLogger;
+
+void metrics_log_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms,
+                    uint32_t device_class, device_type_t device_type) {
+  BluetoothMetricsLogger::GetInstance()->LogPairEvent(disconnect_reason,
+    timestamp_ms, device_class, device_type);
+}
+
+void metrics_log_wake_event(wake_event_type_t type, const char* requestor,
+                    const char* name, uint64_t timestamp_ms) {
+  std::string requestor_str(requestor);
+  std::string name_str(name);
+  BluetoothMetricsLogger::GetInstance()->LogWakeEvent(type, requestor_str,
+    name_str, timestamp_ms);
+}
+
+void metrics_log_scan_event(bool start, const char* initator, scan_tech_t type,
+                    uint32_t results, uint64_t timestamp_ms) {
+  std::string initator_str(initator);
+  BluetoothMetricsLogger::GetInstance()->LogScanEvent(start, initator_str, type,
+    results, timestamp_ms);
+}
+
+void metrics_log_bluetooth_session_start(connection_tech_t connection_tech_type,
+                                uint64_t timestamp_ms) {
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      connection_tech_type, 0);
+}
+
+void metrics_log_bluetooth_session_end(disconnect_reason_t disconnect_reason,
+  uint64_t timestamp_ms) {
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+    disconnect_reason, timestamp_ms);
+}
+
+void metrics_log_bluetooth_session_device_info(uint32_t device_class,
+                                     device_type_t device_type) {
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
+    device_class, device_type);
+}
+
+void metrics_log_a2dp_session(A2dpSessionMetrics_t* metrics) {
+  system_bt_osi::A2dpSessionMetrics metrics_obj;
+  metrics_obj.audio_duration_ms = metrics->audio_duration_ms;
+  metrics_obj.media_timer_min_ms = metrics->media_timer_min_ms;
+  metrics_obj.media_timer_max_ms = metrics->media_timer_max_ms;
+  metrics_obj.media_timer_avg_ms = metrics->media_timer_avg_ms;
+  metrics_obj.total_scheduling_count = metrics->total_scheduling_count;
+  metrics_obj.buffer_overruns_max_count = metrics->buffer_overruns_max_count;
+  metrics_obj.buffer_overruns_total = metrics->buffer_overruns_total;
+  metrics_obj.buffer_underruns_average = metrics->buffer_underruns_average;
+  metrics_obj.buffer_underruns_count = metrics->buffer_underruns_count;
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics_obj);
+}
+
+void metrics_write_base64(int fd, bool clear) {
+  BluetoothMetricsLogger::GetInstance()->WriteBase64(fd, clear);
 }
index f013236..f634516 100644 (file)
  *  limitations under the License.
  *
  ******************************************************************************/
+#define LOG_TAG "bt_osi_metrics"
 
+#include <unistd.h>
+#include <algorithm>
+#include <cerrno>
+#include <chrono>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <mutex>
 
-#define LOG_TAG "bt_osi_metrics"
+#include <base/base64.h>
+#include <base/logging.h>
+
+#include "osi/include/leaky_bonded_queue.h"
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+#include "osi/include/time.h"
 
-extern "C" {
 #include "osi/include/metrics.h"
+#include "osi/include/metrics_cpp.h"
+
+
+namespace system_bt_osi {
+
+// Maximum number of log entries for each repeated field
+#define MAX_NUM_BLUETOOTH_SESSION 50
+#define MAX_NUM_PAIR_EVENT 50
+#define MAX_NUM_WAKE_EVENT 50
+#define MAX_NUM_SCAN_EVENT 50
+
+static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
+                              int64_t ct_b) {
+  if (ct_a > 0 && ct_b > 0) {
+    return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
+  } else if (ct_b > 0) {
+    return avg_b;
+  } else {
+    return avg_a;
+  }
+}
+
+static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
+                                int64_t ct_b) {
+  if (ct_a > 0 && ct_b > 0) {
+    return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
+  } else if (ct_b > 0) {
+    return avg_b;
+  } else {
+    return avg_a;
+  }
+}
+
+void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
+  if (metrics.audio_duration_ms > 0) {
+    audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
+    audio_duration_ms += metrics.audio_duration_ms;
+  }
+  if (metrics.media_timer_min_ms > 0) {
+    if (media_timer_min_ms < 0) {
+      media_timer_min_ms = metrics.media_timer_min_ms;
+    } else {
+      media_timer_min_ms =
+          std::min(media_timer_min_ms, metrics.media_timer_min_ms);
+    }
+  }
+  if (metrics.media_timer_max_ms > 0) {
+    media_timer_max_ms =
+        std::max(media_timer_max_ms, metrics.media_timer_max_ms);
+  }
+  if (metrics.media_timer_avg_ms > 0 && metrics.total_scheduling_count > 0) {
+    if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
+      media_timer_avg_ms = metrics.media_timer_avg_ms;
+      total_scheduling_count = metrics.total_scheduling_count;
+    } else {
+      media_timer_avg_ms = combine_averages(
+          media_timer_avg_ms, total_scheduling_count,
+          metrics.media_timer_avg_ms, metrics.total_scheduling_count);
+      total_scheduling_count += metrics.total_scheduling_count;
+    }
+  }
+  if (metrics.buffer_overruns_max_count > 0) {
+    buffer_overruns_max_count =
+        std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
+  }
+  if (metrics.buffer_overruns_total > 0) {
+    buffer_overruns_total =
+        std::max(static_cast<int32_t>(0), buffer_overruns_total);
+    buffer_overruns_total += metrics.buffer_overruns_total;
+  }
+  if (metrics.buffer_underruns_average > 0 &&
+      metrics.buffer_underruns_count > 0) {
+    if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
+      buffer_underruns_average = metrics.buffer_underruns_average;
+      buffer_underruns_count = metrics.buffer_underruns_count;
+    } else {
+      buffer_underruns_average = combine_averages(
+          metrics.buffer_underruns_average, metrics.buffer_underruns_count,
+          buffer_underruns_average, buffer_underruns_count);
+      buffer_underruns_count += metrics.buffer_underruns_count;
+    }
+  }
+}
+
+bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
+  return audio_duration_ms == rhs.audio_duration_ms &&
+         media_timer_min_ms == rhs.media_timer_min_ms &&
+         media_timer_max_ms == rhs.media_timer_max_ms &&
+         media_timer_avg_ms == rhs.media_timer_avg_ms &&
+         total_scheduling_count == rhs.total_scheduling_count &&
+         buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
+         buffer_overruns_total == rhs.buffer_overruns_total &&
+         buffer_underruns_average == rhs.buffer_underruns_average &&
+         buffer_underruns_count == rhs.buffer_underruns_count;
+}
+
+struct BluetoothMetricsLogger::impl {
+  // TODO(siyuanh): Implement for linux
+};
+
+BluetoothMetricsLogger::BluetoothMetricsLogger() : pimpl_(new impl) {}
+
+void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
+                                          uint64_t timestamp_ms,
+                                          uint32_t device_class,
+                                          device_type_t device_type) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
+                                          const std::string& requestor,
+                                          const std::string& name,
+                                          uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::LogScanEvent(bool start,
+                                          const std::string& initator,
+                                          scan_tech_t type, uint32_t results,
+                                          uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::LogBluetoothSessionStart(
+    connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::LogBluetoothSessionEnd(
+    const std::string& disconnect_reason, uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
+    uint32_t device_class, device_type_t device_type) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::LogA2dpSession(
+    const A2dpSessionMetrics& a2dp_session_metrics) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
+                                               bool clear) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::CutoffSession() {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::Build() {
+  // TODO(siyuanh): Implement for linux
+}
+
+void BluetoothMetricsLogger::Reset() {
+  // TODO(siyuanh): Implement for linux
+}
+
+}  // namespace system_bt_osi
+
+void metrics_log_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms,
+                    uint32_t device_class, device_type_t device_type) {
+  // TODO(siyuanh): Implement for linux
+}
+
+void metrics_log_wake_event(wake_event_type_t type, const char* requestor,
+                    const char* name, uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
 }
 
-void metrics_pair_event(uint32_t disconnect_reason, uint64_t timestamp_ms,
-                        uint32_t device_class, device_type_t device_type) {
-  //TODO(jpawlowski): implement
+void metrics_log_scan_event(bool start, const char* initator, scan_tech_t type,
+                    uint32_t results, uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
 }
 
-void metrics_wake_event(wake_event_type_t type, const char *requestor,
-                        const char *name, uint64_t timestamp_ms) {
-  //TODO(jpawlowski): implement
+void metrics_log_bluetooth_session_start(connection_tech_t connection_tech_type,
+                                uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
 }
 
-void metrics_scan_event(bool start, const char *initator, scan_tech_t type,
-                        uint32_t results, uint64_t timestamp_ms) {
-  //TODO(jpawlowski): implement
+void metrics_log_bluetooth_session_end(const char* disconnect_reason,
+  uint64_t timestamp_ms) {
+  // TODO(siyuanh): Implement for linux
 }
 
-void metrics_a2dp_session(int64_t session_duration_sec,
-                          const char *disconnect_reason,
-                          uint32_t device_class,
-                          int32_t media_timer_min_ms,
-                          int32_t media_timer_max_ms,
-                          int32_t media_timer_avg_ms,
-                          int32_t buffer_overruns_max_count,
-                          int32_t buffer_overruns_total,
-                          float buffer_underruns_average,
-                          int32_t buffer_underruns_count) {
-  //TODO(jpawlowski): implement
+void metrics_log_bluetooth_session_device_info(uint32_t device_class,
+                                     device_type_t device_type) {
+  // TODO(siyuanh): Implement for linux
 }
 
-void metrics_write(int fd, bool clear) {
-  //TODO(jpawlowski): implement
+void metrics_log_a2dp_session(A2dpSessionMetrics_t* metrics) {
+  // TODO(siyuanh): Implement for linux
 }
 
-void metrics_print(int fd, bool clear) {
-  //TODO(jpawlowski): implement
+void metrics_write_base64(int fd, bool clear) {
+  // TODO(siyuanh): Implement for linux
 }
index 9a233ad..14c1ef2 100644 (file)
@@ -24,6 +24,21 @@ message BluetoothLog {
 
   // Scan event information.
   repeated ScanEvent scan_event = 4;
+
+  // Number of bonded devices.
+  optional int32 num_bonded_devices = 5;
+
+  // Number of BluetoothSession including discarded ones beyond capacity
+  optional int64 num_bluetooth_session = 6;
+
+  // Number of PairEvent including discarded ones beyond capacity
+  optional int64 num_pair_event = 7;
+
+  // Number of WakeEvent including discarded ones beyond capacity
+  optional int64 num_wake_event = 8;
+
+  // Number of ScanEvent including discarded ones beyond capacity
+  optional int64 num_scan_event = 9;
 }
 
 // The information about the device.
@@ -63,6 +78,17 @@ message BluetoothSession {
      CONNECTION_TECHNOLOGY_TYPE_BREDR = 2;
   }
 
+  enum DisconnectReasonType {
+    UNKNOWN = 0;
+
+    // A metrics dump takes a snapshot of current Bluetooth session and thus
+    // is not a real disconnect, but a discontinuation in metrics logging.
+    // This enum indicates this situation.
+    METRICS_DUMP = 1;
+
+    NEXT_START_WITHOUT_END_PREVIOUS = 2;
+  }
+
   // Duration of the session.
   optional int64 session_duration_sec = 2;
 
@@ -70,7 +96,7 @@ message BluetoothSession {
   optional ConnectionTechnologyType connection_technology_type = 3;
 
   // Reason for disconnecting.
-  optional string disconnect_reason = 4;
+  optional string disconnect_reason = 4 [deprecated=true];
 
   // The information about the device which it is connected to.
   optional DeviceInfo device_connected_to = 5;
@@ -78,8 +104,11 @@ message BluetoothSession {
   // The information about the RFComm session.
   optional RFCommSession rfcomm_session = 6;
 
-  // The information about the A2DP session.
+  // The information about the A2DP audio session.
   optional A2DPSession a2dp_session = 7;
+
+  // Numeric reason for disconnecting as defined in metrics.h
+  optional DisconnectReasonType disconnect_reason_type = 8;
 }
 
 message RFCommSession {
@@ -91,7 +120,7 @@ message RFCommSession {
   optional int32 tx_bytes = 2;
 }
 
-// Session information that gets logged for every A2DP session.
+// Session information that gets logged for A2DP session.
 message A2DPSession {
 
   // Media timer in milliseconds.
@@ -114,6 +143,9 @@ message A2DPSession {
 
   // Buffer underruns count.
   optional int32 buffer_underruns_count = 7;
+
+  // Total audio time in this A2DP session
+  optional int64 audio_duration_millis = 8;
 }
 
 message PairEvent {
index fc19cc4..9681bd0 100644 (file)
@@ -294,7 +294,7 @@ static void update_wakelock_acquired_stats(bt_status_t acquired_status) {
 
   pthread_mutex_unlock(&monitor);
 
-  metrics_wake_event(WAKE_EVENT_ACQUIRED, NULL, WAKE_LOCK_ID, now_ms);
+  metrics_log_wake_event(WAKE_EVENT_ACQUIRED, "", "", now_ms);
 }
 
 //
@@ -338,7 +338,7 @@ static void update_wakelock_released_stats(bt_status_t released_status) {
 
   pthread_mutex_unlock(&monitor);
 
-  metrics_wake_event(WAKE_EVENT_RELEASED, NULL, WAKE_LOCK_ID, now_ms);
+  metrics_log_wake_event(WAKE_EVENT_RELEASED, "", "", now_ms);
 }
 
 void wakelock_debug_dump(int fd) {
diff --git a/osi/test/leaky_bonded_queue_test.cpp b/osi/test/leaky_bonded_queue_test.cpp
new file mode 100644 (file)
index 0000000..c538101
--- /dev/null
@@ -0,0 +1,242 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2016 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <base/logging.h>
+
+#include "osi/include/leaky_bonded_queue.h"
+
+namespace testing {
+
+using system_bt_osi::LeakyBondedQueue;
+
+#define ITEM_EQ(a, b)              \
+  do {                             \
+    EXPECT_EQ(a, b);               \
+    EXPECT_EQ(a->index, b->index); \
+  } while (0)
+
+class Item {
+ public:
+  Item(int i) { index = i; }
+  virtual ~Item() {}
+  int index;
+};
+
+class MockItem : public Item {
+ public:
+  MockItem(int i) : Item(i) {}
+  ~MockItem() { Destruct(); }
+  MOCK_METHOD0(Destruct, void());
+};
+
+TEST(LeakyBondedQueueTest, TestEnqueueDequeue) {
+  MockItem* item1 = new MockItem(1);
+  MockItem* item2 = new MockItem(2);
+  MockItem* item3 = new MockItem(3);
+  MockItem* item4 = new MockItem(4);
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(3);
+  EXPECT_EQ(queue->Capacity(), static_cast<size_t>(3));
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  queue->Enqueue(item2);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  queue->Enqueue(item3);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(3));
+  EXPECT_CALL(*item1, Destruct()).Times(1);
+  queue->Enqueue(item4);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(3));
+  MockItem* item2_2 = queue->Dequeue();
+  MockItem* item3_3 = queue->Dequeue();
+  MockItem* item4_4 = queue->Dequeue();
+  EXPECT_THAT(item2_2, NotNull());
+  ITEM_EQ(item2_2, item2);
+  EXPECT_THAT(item3_3, NotNull());
+  ITEM_EQ(item3_3, item3);
+  EXPECT_THAT(item4_4, NotNull());
+  ITEM_EQ(item4_4, item4);
+  LOG(INFO) << "All done release items";
+  EXPECT_CALL(*item2_2, Destruct()).Times(1);
+  delete item2_2;
+  EXPECT_CALL(*item3_3, Destruct()).Times(1);
+  delete item3_3;
+  EXPECT_CALL(*item4_4, Destruct()).Times(1);
+  delete item4_4;
+  delete queue;
+}
+
+TEST(LeakyBondedQueueTest, TestEnqueueDequeue2) {
+  MockItem* item1 = new MockItem(1);
+  MockItem* item2 = new MockItem(2);
+  MockItem* item3 = new MockItem(3);
+  MockItem* item4 = new MockItem(4);
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2);
+  EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2));
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  MockItem* item1_1 = queue->Dequeue();
+  ITEM_EQ(item1, item1_1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item2);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  queue->Enqueue(item3);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item2, Destruct()).Times(1);
+  queue->Enqueue(item4);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item3, Destruct()).Times(1);
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  MockItem* item4_4_4 = queue->Dequeue();
+  MockItem* item1_1_1 = queue->Dequeue();
+  ITEM_EQ(item4_4_4, item4);
+  ITEM_EQ(item1_1_1, item1);
+  EXPECT_CALL(*item1_1_1, Destruct()).Times(1);
+  delete item1_1_1;
+  EXPECT_CALL(*item4_4_4, Destruct()).Times(1);
+  delete item4_4_4;
+  delete queue;
+}
+
+TEST(LeakyBondedQueueTest, TestEnqueuePop) {
+  MockItem* item1 = new MockItem(1);
+  MockItem* item2 = new MockItem(2);
+  MockItem* item3 = new MockItem(3);
+  MockItem* item4 = new MockItem(4);
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2);
+  EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2));
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  MockItem* item1_1 = queue->Dequeue();
+  ITEM_EQ(item1, item1_1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item2);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  queue->Enqueue(item3);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  MockItem* item2_2 = queue->EnqueueWithPop(item4);
+  EXPECT_THAT(item2_2, NotNull());
+  ITEM_EQ(item2_2, item2);
+  EXPECT_CALL(*item2, Destruct()).Times(1);
+  delete item2_2;
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  MockItem* item3_3 = queue->EnqueueWithPop(item1);
+  EXPECT_THAT(item3_3, NotNull());
+  ITEM_EQ(item3_3, item3);
+  EXPECT_CALL(*item3, Destruct()).Times(1);
+  delete item3_3;
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  MockItem* item4_4_4 = queue->Dequeue();
+  MockItem* item1_1_1 = queue->Dequeue();
+  ITEM_EQ(item4_4_4, item4);
+  ITEM_EQ(item1_1_1, item1);
+  EXPECT_CALL(*item1_1_1, Destruct()).Times(1);
+  delete item1_1_1;
+  EXPECT_CALL(*item4_4_4, Destruct()).Times(1);
+  delete item4_4_4;
+  delete queue;
+}
+
+TEST(LeakyBondedQueueTest, TestQueueClear) {
+  MockItem* item1 = new MockItem(1);
+  MockItem* item2 = new MockItem(2);
+  MockItem* item3 = new MockItem(3);
+  MockItem* item4 = new MockItem(4);
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2);
+  EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2));
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  MockItem* item1_1 = queue->Dequeue();
+  ITEM_EQ(item1, item1_1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item2);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  queue->Enqueue(item3);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item2, Destruct()).Times(1);
+  queue->Enqueue(item4);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item3, Destruct()).Times(1);
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item1, Destruct()).Times(1);
+  EXPECT_CALL(*item4, Destruct()).Times(1);
+  queue->Clear();
+  delete queue;
+}
+
+TEST(LeakyBondedQueueTest, TestQueueFree) {
+  MockItem* item1 = new MockItem(1);
+  MockItem* item2 = new MockItem(2);
+  MockItem* item3 = new MockItem(3);
+  MockItem* item4 = new MockItem(4);
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2);
+  EXPECT_EQ(queue->Capacity(), static_cast<size_t>(2));
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  MockItem* item1_1 = queue->Dequeue();
+  ITEM_EQ(item1, item1_1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(0));
+  queue->Enqueue(item2);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(1));
+  queue->Enqueue(item3);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item2, Destruct()).Times(1);
+  queue->Enqueue(item4);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item3, Destruct()).Times(1);
+  queue->Enqueue(item1);
+  EXPECT_EQ(queue->Length(), static_cast<size_t>(2));
+  EXPECT_CALL(*item1, Destruct()).Times(1);
+  EXPECT_CALL(*item4, Destruct()).Times(1);
+  delete queue;
+}
+
+TEST(LeakyBondedQueueTest, TestPushNull) {
+  MockItem* item1 = nullptr;
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2);
+  queue->Enqueue(item1);
+  MockItem* item1_1 = queue->Dequeue();
+  EXPECT_THAT(item1_1, IsNull());
+}
+
+TEST(LeakyBondedQueueTest, TestPushNullOverflowQueue) {
+  MockItem* item1 = nullptr;
+  MockItem* item2 = nullptr;
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(1);
+  queue->Enqueue(item1);
+  queue->Enqueue(item2);
+  MockItem* item2_2 = queue->Dequeue();
+  EXPECT_THAT(item2_2, IsNull());
+}
+
+TEST(LeakyBondedQueueTest, TestPushNullDeleteQueue) {
+  MockItem* item1 = nullptr;
+  MockItem* item2 = nullptr;
+  LeakyBondedQueue<MockItem>* queue = new LeakyBondedQueue<MockItem>(2);
+  queue->Enqueue(item1);
+  queue->Enqueue(item2);
+  delete queue;
+}
+}
diff --git a/osi/test/metrics_test.cpp b/osi/test/metrics_test.cpp
new file mode 100644 (file)
index 0000000..597e4b3
--- /dev/null
@@ -0,0 +1,805 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2016 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+#include <chrono>
+#include <cstdint>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <base/logging.h>
+
+#include "osi/include/metrics.h"
+#include "osi/include/metrics_cpp.h"
+#include "osi/include/time.h"
+#include "osi/src/protos/bluetooth.pb.h"
+
+#define BTM_COD_MAJOR_AUDIO_TEST 0x04
+
+namespace testing {
+
+using clearcut::connectivity::A2DPSession;
+using clearcut::connectivity::BluetoothLog;
+using clearcut::connectivity::BluetoothSession;
+using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType;
+using clearcut::connectivity::BluetoothSession_DisconnectReasonType;
+using clearcut::connectivity::DeviceInfo;
+using clearcut::connectivity::DeviceInfo_DeviceType;
+using clearcut::connectivity::PairEvent;
+using clearcut::connectivity::RFCommSession;
+using clearcut::connectivity::ScanEvent;
+using clearcut::connectivity::ScanEvent_ScanTechnologyType;
+using clearcut::connectivity::ScanEvent_ScanEventType;
+using clearcut::connectivity::WakeEvent;
+using clearcut::connectivity::WakeEvent_WakeEventType;
+using system_bt_osi::BluetoothMetricsLogger;
+using system_bt_osi::A2dpSessionMetrics;
+
+namespace {
+const size_t kMaxEventGenerationLimit = 5000;
+}
+
+uint64_t metrics_time_get_os_boottime_us(void) {
+  struct timespec ts_now;
+  clock_gettime(CLOCK_BOOTTIME, &ts_now);
+
+  return ((uint64_t)ts_now.tv_sec * 1000000L) +
+         ((uint64_t)ts_now.tv_nsec / 1000);
+}
+
+/*
+ * Get current OS boot time in millisecond
+ */
+static int64_t time_get_os_boottime_ms(void) {
+  return metrics_time_get_os_boottime_us() / 1000;
+}
+
+static void sleep_ms(int64_t t) {
+  std::this_thread::sleep_for(std::chrono::milliseconds(t));
+}
+
+DeviceInfo* MakeDeviceInfo(int32_t device_class,
+                           DeviceInfo_DeviceType device_type) {
+  DeviceInfo* info = new DeviceInfo();
+  info->set_device_class(device_class);
+  info->set_device_type(device_type);
+  return info;
+}
+
+PairEvent* MakePairEvent(int32_t disconnect_reason, int64_t timestamp_ms,
+                         DeviceInfo* device_info) {
+  PairEvent* event = new PairEvent();
+  event->set_disconnect_reason(disconnect_reason);
+  event->set_event_time_millis(timestamp_ms);
+  if (device_info) event->set_allocated_device_paired_with(device_info);
+  return event;
+}
+
+WakeEvent* MakeWakeEvent(WakeEvent_WakeEventType event_type,
+                         const std::string& requestor, const std::string& name,
+                         int64_t timestamp_ms) {
+  WakeEvent* event = new WakeEvent();
+  event->set_wake_event_type(event_type);
+  event->set_requestor(requestor);
+  event->set_name(name);
+  event->set_event_time_millis(timestamp_ms);
+  return event;
+}
+
+ScanEvent* MakeScanEvent(ScanEvent_ScanEventType event_type,
+                         const std::string& initiator,
+                         ScanEvent_ScanTechnologyType tech_type,
+                         int32_t num_results, int64_t timestamp_ms) {
+  ScanEvent* event = new ScanEvent();
+  event->set_scan_event_type(event_type);
+  event->set_initiator(initiator);
+  event->set_scan_technology_type(tech_type);
+  event->set_number_results(num_results);
+  event->set_event_time_millis(timestamp_ms);
+  return event;
+}
+
+A2DPSession* MakeA2DPSession(const A2dpSessionMetrics& metrics) {
+  A2DPSession* session = new A2DPSession();
+  session->set_media_timer_min_millis(metrics.media_timer_min_ms);
+  session->set_media_timer_max_millis(metrics.media_timer_max_ms);
+  session->set_media_timer_avg_millis(metrics.media_timer_avg_ms);
+  session->set_buffer_overruns_max_count(metrics.buffer_overruns_max_count);
+  session->set_buffer_overruns_total(metrics.buffer_overruns_total);
+  session->set_buffer_underruns_average(metrics.buffer_underruns_average);
+  session->set_buffer_underruns_count(metrics.buffer_underruns_count);
+  session->set_audio_duration_millis(metrics.audio_duration_ms);
+  return session;
+}
+
+BluetoothSession* MakeBluetoothSession(
+    int64_t session_duration_sec,
+    BluetoothSession_ConnectionTechnologyType conn_type,
+    BluetoothSession_DisconnectReasonType disconnect_reason,
+    DeviceInfo* device_info, RFCommSession* rfcomm_session,
+    A2DPSession* a2dp_session) {
+  BluetoothSession* session = new BluetoothSession();
+  if (a2dp_session) session->set_allocated_a2dp_session(a2dp_session);
+  if (rfcomm_session) session->set_allocated_rfcomm_session(rfcomm_session);
+  if (device_info) session->set_allocated_device_connected_to(device_info);
+  session->set_session_duration_sec(session_duration_sec);
+  session->set_connection_technology_type(conn_type);
+  session->set_disconnect_reason_type(disconnect_reason);
+  return session;
+}
+
+BluetoothLog* MakeBluetoothLog(std::vector<BluetoothSession*> bt_sessions,
+                               std::vector<PairEvent*> pair_events,
+                               std::vector<WakeEvent*> wake_events,
+                               std::vector<ScanEvent*> scan_events) {
+  BluetoothLog* bt_log = new BluetoothLog();
+  for (BluetoothSession* session : bt_sessions) {
+    bt_log->mutable_session()->AddAllocated(session);
+  }
+  bt_sessions.clear();
+  for (PairEvent* event : pair_events) {
+    bt_log->mutable_pair_event()->AddAllocated(event);
+  }
+  pair_events.clear();
+  for (WakeEvent* event : wake_events) {
+    bt_log->mutable_wake_event()->AddAllocated(event);
+  }
+  wake_events.clear();
+  for (ScanEvent* event : scan_events) {
+    bt_log->mutable_scan_event()->AddAllocated(event);
+  }
+  scan_events.clear();
+  return bt_log;
+}
+
+void GenerateWakeEvents(size_t start, size_t end,
+                        std::vector<WakeEvent*>* wake_events) {
+  for (size_t i = start; i < end; ++i) {
+    wake_events->push_back(MakeWakeEvent(
+        i % 2 == 0 ? WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED
+                   : WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED,
+        "TEST_REQ", "TEST_NAME", i));
+  }
+}
+
+#define COMPARE_A2DP_METRICS(a, b)                                       \
+  do {                                                                   \
+    EXPECT_EQ(a.audio_duration_ms, b.audio_duration_ms);                 \
+    EXPECT_EQ(a.media_timer_min_ms, b.media_timer_min_ms);               \
+    EXPECT_EQ(a.media_timer_max_ms, b.media_timer_max_ms);               \
+    EXPECT_EQ(a.media_timer_avg_ms, b.media_timer_avg_ms);               \
+    EXPECT_EQ(a.total_scheduling_count, b.total_scheduling_count);       \
+    EXPECT_EQ(a.buffer_overruns_max_count, b.buffer_overruns_max_count); \
+    EXPECT_EQ(a.buffer_overruns_total, b.buffer_overruns_total);         \
+    EXPECT_THAT(a.buffer_underruns_average,                              \
+                FloatNear(b.buffer_underruns_average, 0.01));            \
+    a.buffer_underruns_average = b.buffer_underruns_average;             \
+    EXPECT_EQ(a.buffer_underruns_count, b.buffer_underruns_count);       \
+  } while (0)
+
+/*
+ * metrics_sum = metrics1 + metrics2
+ */
+TEST(BluetoothA2DPSessionMetricsTest, TestUpdateNormal) {
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics1.audio_duration_ms = 10;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 35;
+  metrics1.media_timer_min_ms = 10;
+  metrics2.media_timer_min_ms = 25;
+  metrics_sum.media_timer_min_ms = 10;
+  metrics1.media_timer_max_ms = 100;
+  metrics2.media_timer_max_ms = 200;
+  metrics_sum.media_timer_max_ms = 200;
+  metrics1.media_timer_avg_ms = 50;
+  metrics1.total_scheduling_count = 50;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics_sum.media_timer_avg_ms = 75;
+  metrics_sum.total_scheduling_count = 100;
+  metrics1.buffer_overruns_max_count = 70;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics_sum.buffer_overruns_max_count = 80;
+  metrics1.buffer_underruns_average = 80;
+  metrics1.buffer_underruns_count = 1200;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 113.33333333;
+  metrics_sum.buffer_underruns_count = 3600;
+  metrics1.Update(metrics2);
+  COMPARE_A2DP_METRICS(metrics1, metrics_sum);
+  EXPECT_TRUE(metrics1 == metrics_sum);
+  EXPECT_EQ(metrics1, metrics_sum);
+}
+
+TEST(BluetoothA2DPSessionMetricsTest, TestUpdateNew) {
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 25;
+  metrics2.media_timer_min_ms = 25;
+  metrics_sum.media_timer_min_ms = 25;
+  metrics2.media_timer_max_ms = 200;
+  metrics_sum.media_timer_max_ms = 200;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics_sum.media_timer_avg_ms = 100;
+  metrics_sum.total_scheduling_count = 50;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics_sum.buffer_overruns_max_count = 80;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 130;
+  metrics_sum.buffer_underruns_count = 2400;
+  metrics1.Update(metrics2);
+  COMPARE_A2DP_METRICS(metrics1, metrics_sum);
+  EXPECT_TRUE(metrics1 == metrics_sum);
+  EXPECT_EQ(metrics1, metrics_sum);
+}
+
+TEST(BluetoothA2DPSessionMetricsTest, TestNullUpdate) {
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 25;
+  metrics2.media_timer_min_ms = 25;
+  metrics_sum.media_timer_min_ms = 25;
+  metrics2.media_timer_max_ms = 200;
+  metrics_sum.media_timer_max_ms = 200;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics_sum.media_timer_avg_ms = 100;
+  metrics_sum.total_scheduling_count = 50;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics_sum.buffer_overruns_max_count = 80;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 130;
+  metrics_sum.buffer_underruns_count = 2400;
+  metrics2.Update(metrics1);
+  COMPARE_A2DP_METRICS(metrics2, metrics_sum);
+  EXPECT_TRUE(metrics2 == metrics_sum);
+  EXPECT_EQ(metrics2, metrics_sum);
+}
+
+TEST(BluetoothA2DPSessionMetricsTest, TestPartialUpdate) {
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics1.audio_duration_ms = 10;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 35;
+  metrics1.media_timer_min_ms = 10;
+  metrics_sum.media_timer_min_ms = 10;
+  metrics1.media_timer_max_ms = 100;
+  metrics_sum.media_timer_max_ms = 100;
+  metrics1.media_timer_avg_ms = 50;
+  metrics1.total_scheduling_count = 50;
+  metrics2.media_timer_avg_ms = 100;
+  metrics_sum.media_timer_avg_ms = 50;
+  metrics_sum.total_scheduling_count = 50;
+  metrics1.buffer_overruns_max_count = 70;
+  metrics_sum.buffer_overruns_max_count = 70;
+  metrics1.buffer_underruns_average = 80;
+  metrics1.buffer_underruns_count = 1200;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 80;
+  metrics_sum.buffer_underruns_count = 1200;
+  metrics1.Update(metrics2);
+  COMPARE_A2DP_METRICS(metrics1, metrics_sum);
+  EXPECT_TRUE(metrics1 == metrics_sum);
+  EXPECT_EQ(metrics1, metrics_sum);
+}
+
+class BluetoothMetricsLoggerTest : public Test {
+ protected:
+  // Use to hold test protos
+  std::vector<PairEvent*> pair_events_;
+  std::vector<WakeEvent*> wake_events_;
+  std::vector<ScanEvent*> scan_events_;
+  std::vector<BluetoothSession*> bt_sessions_;
+  int64_t num_pair_event_ = 0;
+  int64_t num_wake_event_ = 0;
+  int64_t num_scan_event_ = 0;
+  int64_t num_bt_session_ = 0;
+  BluetoothLog* bt_log_;
+  std::string bt_log_str_;
+  std::string bt_log_ascii_str_;
+
+  void UpdateLog() {
+    for (BluetoothSession* session : bt_sessions_) {
+      bt_log_->mutable_session()->AddAllocated(session);
+    }
+    if (num_bt_session_ > 0) {
+      bt_log_->set_num_bluetooth_session(num_bt_session_);
+    } else if (bt_sessions_.size() > 0) {
+      bt_log_->set_num_bluetooth_session(bt_sessions_.size());
+    }
+    bt_sessions_.clear();
+    for (PairEvent* event : pair_events_) {
+      bt_log_->mutable_pair_event()->AddAllocated(event);
+    }
+    if (num_pair_event_ > 0) {
+      bt_log_->set_num_pair_event(num_pair_event_);
+    } else if (pair_events_.size() > 0) {
+      bt_log_->set_num_pair_event(pair_events_.size());
+    }
+    pair_events_.clear();
+    for (WakeEvent* event : wake_events_) {
+      bt_log_->mutable_wake_event()->AddAllocated(event);
+    }
+    if (num_wake_event_ > 0) {
+      bt_log_->set_num_wake_event(num_wake_event_);
+    } else if (wake_events_.size() > 0) {
+      bt_log_->set_num_wake_event(wake_events_.size());
+    }
+    wake_events_.clear();
+    for (ScanEvent* event : scan_events_) {
+      bt_log_->mutable_scan_event()->AddAllocated(event);
+    }
+    if (num_scan_event_ > 0) {
+      bt_log_->set_num_scan_event(num_scan_event_);
+    } else if (scan_events_.size() > 0) {
+      bt_log_->set_num_scan_event(scan_events_.size());
+    }
+    scan_events_.clear();
+    bt_log_->SerializeToString(&bt_log_str_);
+  }
+
+  void ClearLog() {
+    for (BluetoothSession* session : bt_sessions_) {
+      session->Clear();
+      delete session;
+    }
+    bt_sessions_.clear();
+    for (PairEvent* event : pair_events_) {
+      event->Clear();
+      delete event;
+    }
+    pair_events_.clear();
+    for (WakeEvent* event : wake_events_) {
+      event->Clear();
+      delete event;
+    }
+    wake_events_.clear();
+    for (ScanEvent* event : scan_events_) {
+      event->Clear();
+      delete event;
+    }
+    scan_events_.clear();
+    bt_log_->Clear();
+  }
+
+  void SetUp() {
+    bt_log_ = new BluetoothLog();
+    // Clear existing metrics entries, if any
+    BluetoothMetricsLogger::GetInstance()->Reset();
+  }
+  void TearDown() {
+    // Clear remaining metrics entries, if any
+    BluetoothMetricsLogger::GetInstance()->Reset();
+    ClearLog();
+    delete bt_log_;
+  }
+
+ public:
+};
+
+TEST_F(BluetoothMetricsLoggerTest, PairEventTest) {
+  pair_events_.push_back(MakePairEvent(
+      35, 12345,
+      MakeDeviceInfo(
+          42, DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR)));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogPairEvent(
+      35, 12345, 42, DEVICE_TYPE_BREDR);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+TEST_F(BluetoothMetricsLoggerTest, WakeEventTest) {
+  wake_events_.push_back(
+      MakeWakeEvent(WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED,
+                    "TEST_REQ", "TEST_NAME", 12345));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
+      WAKE_EVENT_ACQUIRED, "TEST_REQ", "TEST_NAME", 12345);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+TEST_F(BluetoothMetricsLoggerTest, WakeEventOverrunTest) {
+  GenerateWakeEvents(kMaxEventGenerationLimit -
+    BluetoothMetricsLogger::kMaxNumWakeEvent,
+    kMaxEventGenerationLimit, &wake_events_);
+  num_wake_event_ = kMaxEventGenerationLimit;
+  UpdateLog();
+  for (size_t i = 0; i < kMaxEventGenerationLimit; ++i) {
+    BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
+        i % 2 == 0 ? WAKE_EVENT_ACQUIRED : WAKE_EVENT_RELEASED,
+        "TEST_REQ", "TEST_NAME", i);
+  }
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+TEST_F(BluetoothMetricsLoggerTest, ScanEventTest) {
+  scan_events_.push_back(MakeScanEvent(
+      ScanEvent_ScanEventType::ScanEvent_ScanEventType_SCAN_EVENT_STOP,
+      "TEST_INITIATOR", ScanEvent_ScanTechnologyType::
+                            ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR,
+      42, 123456));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogScanEvent(
+      false, "TEST_INITIATOR", SCAN_TECH_TYPE_BREDR, 42, 123456);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionTest) {
+  bt_sessions_.push_back(MakeBluetoothSession(
+      10,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE,
+      BluetoothSession_DisconnectReasonType::
+          BluetoothSession_DisconnectReasonType_UNKNOWN,
+      nullptr, nullptr, nullptr));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_LE, 123456);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+      DISCONNECT_REASON_UNKNOWN, 133456);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionDumpBeforeEndTest) {
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE,
+      BluetoothSession_DisconnectReasonType::
+          BluetoothSession_DisconnectReasonType_METRICS_DUMP,
+      nullptr, nullptr, nullptr));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_LE, time_get_os_boottime_ms());
+  sleep_ms(1000);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionStartBeforeEndTest) {
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
+      BluetoothSession_DisconnectReasonType::
+          BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS,
+      nullptr, nullptr, nullptr));
+  bt_sessions_.push_back(MakeBluetoothSession(
+      2,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE,
+      BluetoothSession_DisconnectReasonType::
+          BluetoothSession_DisconnectReasonType_METRICS_DUMP,
+      nullptr, nullptr, nullptr));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
+  sleep_ms(1000);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_LE, 0);
+  sleep_ms(2000);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+/*
+ * Test Case: A2DPSessionTwoUpdatesTest
+ *
+ * 1. Create Instance
+ * 2. LogBluetoothSessionStart
+ * 3. LogBluetoothSessionDeviceInfo
+ * 4. LogA2dpSession
+ * 5. LogA2dpSession
+ * 6. LogBluetoothSessionEnd
+ * 7. WriteString
+ *
+ */
+TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesTest) {
+  /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics1.audio_duration_ms = 10;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 35;
+  metrics1.media_timer_min_ms = 10;
+  metrics2.media_timer_min_ms = 25;
+  metrics_sum.media_timer_min_ms = 10;
+  metrics1.media_timer_max_ms = 100;
+  metrics2.media_timer_max_ms = 200;
+  metrics_sum.media_timer_max_ms = 200;
+  metrics1.media_timer_avg_ms = 50;
+  metrics1.total_scheduling_count = 50;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics_sum.media_timer_avg_ms = 75;
+  metrics_sum.total_scheduling_count = 100;
+  metrics1.buffer_overruns_max_count = 70;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics_sum.buffer_overruns_max_count = 80;
+  metrics1.buffer_underruns_average = 80;
+  metrics1.buffer_underruns_count = 1200;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 113.33333333;
+  metrics_sum.buffer_underruns_count = 3600;
+  DeviceInfo* info = MakeDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST,
+      DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+  A2DPSession* session = MakeA2DPSession(metrics_sum);
+  bt_sessions_.push_back(MakeBluetoothSession(
+      10,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+      BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN,
+      info, nullptr, session));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_BREDR, 123456);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST, DEVICE_TYPE_BREDR);
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+      DISCONNECT_REASON_UNKNOWN, 133456);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+/*
+ * Test Case: A2DPSessionTwoUpdatesSeparatedbyDumpTest
+ *
+ * 1. Create Instance
+ * 2. LogBluetoothSessionStart
+ * 3. LogBluetoothSessionDeviceInfo
+ * 4. LogA2dpSession
+ * 5. WriteString
+ * 6. LogA2dpSession
+ * 7. LogBluetoothSessionEnd
+ * 8. WriteString
+ *
+ */
+TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesSeparatedbyDumpTest) {
+  /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  metrics1.audio_duration_ms = 10;
+  metrics2.audio_duration_ms = 25;
+  metrics1.media_timer_min_ms = 10;
+  metrics2.media_timer_min_ms = 25;
+  metrics1.media_timer_max_ms = 100;
+  metrics2.media_timer_max_ms = 200;
+  metrics1.media_timer_avg_ms = 50;
+  metrics1.total_scheduling_count = 50;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics1.buffer_overruns_max_count = 70;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics1.buffer_underruns_average = 80;
+  metrics1.buffer_underruns_count = 1200;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  DeviceInfo* info = MakeDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST,
+      DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+  A2DPSession* session = MakeA2DPSession(metrics1);
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+      BluetoothSession_DisconnectReasonType::
+          BluetoothSession_DisconnectReasonType_METRICS_DUMP,
+      info, nullptr, session));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST, DEVICE_TYPE_BREDR);
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
+  sleep_ms(1000);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+  ClearLog();
+  info = MakeDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST,
+      DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+  session = MakeA2DPSession(metrics2);
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+      BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN,
+      info, nullptr, session));
+  UpdateLog();
+  sleep_ms(1000);
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+      DISCONNECT_REASON_UNKNOWN, 0);
+  msg_str.clear();
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+/*
+ * Test Case 1: A2DPSessionOnlyTest
+ *
+ * 1. Create Instance
+ * 4. LogA2dpSession
+ * 5. WriteString
+ * 6. LogA2dpSession
+ * 8. WriteString
+ *
+ */
+TEST_F(BluetoothMetricsLoggerTest, A2DPSessionOnlyTest) {
+  /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics1.audio_duration_ms = 10;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 35;
+  metrics1.media_timer_min_ms = 10;
+  metrics2.media_timer_min_ms = 25;
+  metrics_sum.media_timer_min_ms = 10;
+  metrics1.media_timer_max_ms = 100;
+  metrics2.media_timer_max_ms = 200;
+  metrics_sum.media_timer_max_ms = 200;
+  metrics1.media_timer_avg_ms = 50;
+  metrics1.total_scheduling_count = 50;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics_sum.media_timer_avg_ms = 75;
+  metrics_sum.total_scheduling_count = 100;
+  metrics1.buffer_overruns_max_count = 70;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics_sum.buffer_overruns_max_count = 80;
+  metrics1.buffer_underruns_average = 80;
+  metrics1.buffer_underruns_count = 1200;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 113.33333333;
+  metrics_sum.buffer_underruns_count = 3600;
+  DeviceInfo* info = MakeDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST,
+      DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+  A2DPSession* session = MakeA2DPSession(metrics_sum);
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+      BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP,
+      info, nullptr, session));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
+  sleep_ms(1000);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+
+/*
+ * Test Case: A2DPSessionDumpBeforeTwoUpdatesTest
+ *
+ * 1. Create Instance
+ * 2. LogBluetoothSessionStart
+ * 3. LogBluetoothSessionDeviceInfo
+ * 5. WriteString
+ * 6. LogA2dpSession
+ * 7. LogA2dpSession
+ * 8. LogBluetoothSessionEnd
+ * 9. WriteString
+ *
+ */
+TEST_F(BluetoothMetricsLoggerTest, A2DPSessionDumpBeforeTwoUpdatesTest) {
+  /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */
+  A2dpSessionMetrics metrics1;
+  A2dpSessionMetrics metrics2;
+  A2dpSessionMetrics metrics_sum;
+  metrics1.audio_duration_ms = 10;
+  metrics2.audio_duration_ms = 25;
+  metrics_sum.audio_duration_ms = 35;
+  metrics1.media_timer_min_ms = 10;
+  metrics2.media_timer_min_ms = 25;
+  metrics_sum.media_timer_min_ms = 10;
+  metrics1.media_timer_max_ms = 100;
+  metrics2.media_timer_max_ms = 200;
+  metrics_sum.media_timer_max_ms = 200;
+  metrics1.media_timer_avg_ms = 50;
+  metrics1.total_scheduling_count = 50;
+  metrics2.media_timer_avg_ms = 100;
+  metrics2.total_scheduling_count = 50;
+  metrics_sum.media_timer_avg_ms = 75;
+  metrics_sum.total_scheduling_count = 100;
+  metrics1.buffer_overruns_max_count = 70;
+  metrics2.buffer_overruns_max_count = 80;
+  metrics_sum.buffer_overruns_max_count = 80;
+  metrics1.buffer_underruns_average = 80;
+  metrics1.buffer_underruns_count = 1200;
+  metrics2.buffer_underruns_average = 130;
+  metrics2.buffer_underruns_count = 2400;
+  metrics_sum.buffer_underruns_average = 113.33333333;
+  metrics_sum.buffer_underruns_count = 3600;
+  DeviceInfo* info = MakeDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST,
+      DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+      BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP,
+      info, nullptr, nullptr));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+      CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST, DEVICE_TYPE_BREDR);
+  sleep_ms(1000);
+  std::string msg_str;
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+  ClearLog();
+  info = MakeDeviceInfo(
+      BTM_COD_MAJOR_AUDIO_TEST,
+      DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR);
+  A2DPSession* session = MakeA2DPSession(metrics_sum);
+  bt_sessions_.push_back(MakeBluetoothSession(
+      1,
+      BluetoothSession_ConnectionTechnologyType::
+          BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR,
+      BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN,
+      info, nullptr, session));
+  UpdateLog();
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
+  BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
+  sleep_ms(1000);
+  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+      DISCONNECT_REASON_UNKNOWN, 0);
+  msg_str.clear();
+  BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str, true);
+  EXPECT_THAT(msg_str, StrEq(bt_log_str_));
+}
+}
index 26e6258..87c7ad9 100644 (file)
@@ -33,7 +33,7 @@
 #include "l2cdefs.h"
 #include "btm_api.h"
 #include "btm_int.h"
-
+#include "device/include/interop.h"
 
 /* callback function declarations */
 void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
@@ -202,12 +202,14 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
             p_tbl->state = AVDT_AD_ST_SEC_ACP;
             p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
 
-            // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
-            tACL_CONN *p_acl_cb = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
-            btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
-                                            HCI_PKT_TYPES_MASK_NO_3_DH1 |
-                                            HCI_PKT_TYPES_MASK_NO_3_DH3 |
-                                            HCI_PKT_TYPES_MASK_NO_3_DH5));
+            if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *)&bd_addr)) {
+                // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
+                tACL_CONN *p_acl_cb = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
+                btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
+                                                HCI_PKT_TYPES_MASK_NO_3_DH1 |
+                                                HCI_PKT_TYPES_MASK_NO_3_DH3 |
+                                                HCI_PKT_TYPES_MASK_NO_3_DH5));
+            }
 
             /* Check the security */
             rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM,
@@ -328,12 +330,14 @@ void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
                         p_tbl->lcid = lcid;
                         p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
 
-                        // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
-                        tACL_CONN *p_acl_cb = btm_bda_to_acl(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
-                        btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
-                                                        HCI_PKT_TYPES_MASK_NO_3_DH1 |
-                                                        HCI_PKT_TYPES_MASK_NO_3_DH3 |
-                                                        HCI_PKT_TYPES_MASK_NO_3_DH5));
+                        if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *) &p_ccb->peer_addr)) {
+                            // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
+                            tACL_CONN *p_acl_cb = btm_bda_to_acl(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
+                            btm_set_packet_types(p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
+                                                            HCI_PKT_TYPES_MASK_NO_3_DH1 |
+                                                            HCI_PKT_TYPES_MASK_NO_3_DH3 |
+                                                            HCI_PKT_TYPES_MASK_NO_3_DH5));
+                        }
 
                         /* Check the security */
                         btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM,
index b4a2562..4819012 100644 (file)
@@ -95,7 +95,7 @@ void btm_acl_init (void)
 **                  NULL if not found.
 **
 *******************************************************************************/
-tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport)
+tACL_CONN *btm_bda_to_acl (const BD_ADDR bda, tBT_TRANSPORT transport)
 {
     tACL_CONN   *p = &btm_cb.acl_db[0];
     UINT16       xx;
@@ -898,6 +898,43 @@ void BTM_SetDefaultLinkPolicy (UINT16 settings)
     btsnd_hcic_write_def_policy_set(settings);
 }
 
+
+void btm_use_preferred_conn_params(BD_ADDR bda) {
+    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
+    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
+
+    /* If there are any preferred connection parameters, set them now */
+    if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
+         (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
+         (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
+         (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
+         (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
+         (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
+         (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
+         ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int &&
+          p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
+          (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) ||
+          (p_lcb->latency > p_dev_rec->conn_params.slave_latency) ||
+          (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout)))
+    {
+        BTM_TRACE_DEBUG ("%s: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", __func__,
+                            p_lcb->handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
+                            p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
+
+        p_lcb->min_interval =  p_dev_rec->conn_params.min_conn_int;
+        p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
+        p_lcb->timeout      = p_dev_rec->conn_params.supervision_tout;
+        p_lcb->latency      = p_dev_rec->conn_params.slave_latency;
+
+        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
+                                           p_dev_rec->conn_params.min_conn_int,
+                                           p_dev_rec->conn_params.max_conn_int,
+                                           p_dev_rec->conn_params.slave_latency,
+                                           p_dev_rec->conn_params.supervision_tout,
+                                           0, 0);
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         btm_read_remote_version_complete
@@ -932,8 +969,10 @@ void btm_read_remote_version_complete (UINT8 *p)
             }
 
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
-            if (p_acl_cb->transport == BT_TRANSPORT_LE)
+            if (p_acl_cb->transport == BT_TRANSPORT_LE) {
                 l2cble_notify_le_connection (p_acl_cb->remote_addr);
+                btm_use_preferred_conn_params(p_acl_cb->remote_addr);
+            }
 #endif  // (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
             break;
         }
@@ -1402,7 +1441,7 @@ UINT16 btm_get_acl_disc_reason_code (void)
 ** Returns          the handle of the connection, or 0xFFFF if none.
 **
 *******************************************************************************/
-UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport)
+UINT16 BTM_GetHCIConnHandle (const BD_ADDR remote_bda, tBT_TRANSPORT transport)
 {
     tACL_CONN   *p;
     BTM_TRACE_DEBUG ("BTM_GetHCIConnHandle");
index 11a0be5..fe44525 100644 (file)
@@ -71,7 +71,7 @@ extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr);
 ** Returns          TRUE if added OK, else FALSE
 **
 *******************************************************************************/
-BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE dev_type,
+BOOLEAN BTM_SecAddBleDevice (const BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE dev_type,
                              tBLE_ADDR_TYPE addr_type)
 {
     BTM_TRACE_DEBUG ("%s: dev_type=0x%x", __func__, dev_type);
@@ -454,11 +454,10 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data)
     tSMP_STATUS res_smp = (res == BTM_SUCCESS) ? SMP_SUCCESS : SMP_OOB_FAIL;
     tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bd_addr);
 
-    BTM_TRACE_DEBUG ("BTM_BleOobDataReply");
+    BTM_TRACE_DEBUG ("%s:", __func__);
 
-    if (p_dev_rec == NULL)
-    {
-        BTM_TRACE_ERROR("BTM_BleOobDataReply() to Unknown device");
+    if (p_dev_rec == NULL) {
+        BTM_TRACE_ERROR("%s: Unknown device", __func__);
         return;
     }
 
@@ -467,6 +466,47 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data)
 #endif
 }
 
+/*******************************************************************************
+**
+** Function         BTM_BleSecureConnectionOobDataReply
+**
+** Description      This function is called to provide the OOB data for
+**                  SMP in response to BTM_LE_OOB_REQ_EVT when secure connection
+**                  data is available
+**
+** Parameters:      bd_addr     - Address of the peer device
+**                  p_c         - pointer to Confirmation.
+**                  p_r         - pointer to Randomizer
+**
+*******************************************************************************/
+void BTM_BleSecureConnectionOobDataReply(BD_ADDR bd_addr,
+                                         uint8_t *p_c, uint8_t *p_r)
+{
+#if SMP_INCLUDED == TRUE
+    tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bd_addr);
+
+    BTM_TRACE_DEBUG ("%s:", __func__);
+
+    if (p_dev_rec == NULL) {
+        BTM_TRACE_ERROR("%s: Unknown device", __func__);
+        return;
+    }
+
+    p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
+
+    tSMP_SC_OOB_DATA oob;
+    memset(&oob, 0, sizeof(tSMP_SC_OOB_DATA));
+
+    oob.peer_oob_data.present = true;
+    memcpy(&oob.peer_oob_data.randomizer, p_r, BT_OCTET16_LEN);
+    memcpy(&oob.peer_oob_data.commitment, p_c, BT_OCTET16_LEN);
+    oob.peer_oob_data.addr_rcvd_from.type = p_dev_rec->ble.ble_addr_type;
+    memcpy(&oob.peer_oob_data.addr_rcvd_from.bda, bd_addr, sizeof(BD_ADDR));
+
+    SMP_SecureConnectionOobDataReply((uint8_t*)&oob);
+#endif
+}
+
 /******************************************************************************
 **
 ** Function         BTM_BleSetConnScanParams
index 25072c5..c7a0b38 100644 (file)
@@ -419,12 +419,12 @@ bool is_address_equal(void *data, void *context)
 ** Returns          Pointer to the record or NULL
 **
 *******************************************************************************/
-tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr)
+tBTM_SEC_DEV_REC *btm_find_dev(const BD_ADDR bd_addr)
 {
     if (!bd_addr)
         return NULL;
 
-    list_node_t *n = list_foreach(btm_cb.sec_dev_rec, is_address_equal, bd_addr);
+    list_node_t *n = list_foreach(btm_cb.sec_dev_rec, is_address_equal, (void*)bd_addr);
     if (n)
         return list_node(n);
 
index 74f1b08..d315c11 100644 (file)
@@ -1131,7 +1131,7 @@ tBTM_STATUS  BTM_CancelRemoteDeviceName (void)
 ** Returns          pointer to entry, or NULL if not found
 **
 *******************************************************************************/
-tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda)
+tBTM_INQ_INFO *BTM_InqDbRead (const BD_ADDR p_bda)
 {
     BTM_TRACE_API ("BTM_InqDbRead: bd addr [%02x%02x%02x%02x%02x%02x]",
                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)
 ** Returns          pointer to entry, or NULL if not found
 **
 *******************************************************************************/
-tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda)
+tINQ_DB_ENT *btm_inq_db_find (const BD_ADDR p_bda)
 {
     UINT16       xx;
     tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
index 88e20ab..c3357c2 100644 (file)
@@ -937,7 +937,7 @@ extern void         btm_process_cancel_complete(UINT8 status, UINT8 mode);
 extern void         btm_event_filter_complete (UINT8 *p);
 extern void         btm_inq_stop_on_ssp(void);
 extern void         btm_inq_clear_ssp(void);
-extern tINQ_DB_ENT *btm_inq_db_find (BD_ADDR p_bda);
+extern tINQ_DB_ENT *btm_inq_db_find (const BD_ADDR p_bda);
 extern BOOLEAN      btm_inq_find_bdaddr (BD_ADDR p_bda);
 
 extern BOOLEAN btm_lookup_eir(BD_ADDR_PTR p_rem_addr);
@@ -983,7 +983,7 @@ extern void         btm_establish_continue (tACL_CONN *p_acl_cb);
 extern void         btm_acl_chk_peer_pkt_type_support (tACL_CONN *p, UINT16 *p_pkt_type);
 /* Read maximum data packet that can be sent over current connection */
 extern UINT16 btm_get_max_packet_size (BD_ADDR addr);
-extern tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport);
+extern tACL_CONN *btm_bda_to_acl (const BD_ADDR bda, tBT_TRANSPORT transport);
 extern BOOLEAN    btm_acl_notif_conn_collision (BD_ADDR bda);
 
 extern void btm_pm_reset(void);
@@ -1060,7 +1060,7 @@ extern BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr);
 extern tBTM_SEC_DEV_REC  *btm_sec_allocate_dev_rec(void);
 extern tBTM_SEC_DEV_REC  *btm_sec_alloc_dev (BD_ADDR bd_addr);
 extern void               btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec);
-extern tBTM_SEC_DEV_REC  *btm_find_dev (BD_ADDR bd_addr);
+extern tBTM_SEC_DEV_REC  *btm_find_dev (const BD_ADDR bd_addr);
 extern tBTM_SEC_DEV_REC  *btm_find_or_alloc_dev (BD_ADDR bd_addr);
 extern tBTM_SEC_DEV_REC  *btm_find_dev_by_handle (UINT16 handle);
 extern tBTM_BOND_TYPE     btm_get_bond_type_dev(BD_ADDR bd_addr);
index d8251da..4f1568a 100644 (file)
@@ -398,7 +398,7 @@ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr,
     if (ret)
     {
         if (!opportunistic)
-            gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE);
+            gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
         else
             GATT_TRACE_DEBUG("%s: connection is opportunistic, not updating app usage",
                             __func__);
index a0dc70b..360dd48 100644 (file)
@@ -2517,7 +2517,7 @@ extern UINT8 *BTM_ReadAllRemoteFeatures (BD_ADDR addr);
 ** Returns          pointer to entry, or NULL if not found
 **
 *******************************************************************************/
-extern tBTM_INQ_INFO *BTM_InqDbRead (BD_ADDR p_bda);
+extern tBTM_INQ_INFO *BTM_InqDbRead (const BD_ADDR p_bda);
 
 
 /*******************************************************************************
@@ -3724,7 +3724,7 @@ extern tBTM_STATUS BTM_SetSsrParams (BD_ADDR remote_bda, UINT16 max_lat,
 ** Returns          the handle of the connection, or 0xFFFF if none.
 **
 *******************************************************************************/
-extern UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport);
+extern UINT16 BTM_GetHCIConnHandle (const BD_ADDR remote_bda, tBT_TRANSPORT transport);
 
 /*******************************************************************************
 **
index 2777d1b..0cc2e18 100644 (file)
@@ -912,7 +912,7 @@ extern "C" {
 ** Returns          TRUE if added OK, else FALSE
 **
 *******************************************************************************/
-extern BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name,
+extern BOOLEAN BTM_SecAddBleDevice (const BD_ADDR bd_addr, BD_NAME bd_name,
                                            tBT_DEVICE_TYPE dev_type, tBLE_ADDR_TYPE addr_type);
 
 /*******************************************************************************
@@ -1236,6 +1236,22 @@ extern void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res);
 *******************************************************************************/
 extern void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data);
 
+/*******************************************************************************
+**
+** Function         BTM_BleSecureConnectionOobDataReply
+**
+** Description      This function is called to provide the OOB data for
+**                  SMP in response to BTM_LE_OOB_REQ_EVT when secure connection
+**                  data is available
+**
+** Parameters:      bd_addr     - Address of the peer device
+**                  p_c         - pointer to Confirmation
+**                  p_r         - pointer to Randomizer.
+**
+*******************************************************************************/
+extern void BTM_BleSecureConnectionOobDataReply(BD_ADDR bd_addr,
+                                                uint8_t *p_c, uint8_t *p_r);
+
 
 /*******************************************************************************
 **
index 3175a50..e8b21fe 100644 (file)
@@ -29,7 +29,6 @@
 #include "bt_target.h"
 #include "l2cdefs.h"
 #include "hcidefs.h"
-#include "bta_api.h"
 
 /*****************************************************************************
 **  Constants
@@ -1189,9 +1188,8 @@ extern BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda);
 **  Return value:   TRUE if update started
 **
 *******************************************************************************/
-extern BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bdRa, UINT16 min_int, UINT16 max_int,
-                                         UINT16 latency, UINT16 timeout,
-                                         tBTA_DM_BLE_CONN_PARAM_CBACK *p_cback);
+extern BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bdRa, UINT16 min_int,
+                                         UINT16 max_int, UINT16 latency, UINT16 timeout);
 
 /*******************************************************************************
 **
index 3a421c3..fe52e31 100644 (file)
@@ -103,9 +103,8 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
 **  Return value:   TRUE if update started
 **
 *******************************************************************************/
-BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int,
-                                  UINT16 max_int, UINT16 latency, UINT16 timeout,
-                                  tBTA_DM_BLE_CONN_PARAM_CBACK *p_callback)
+BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
+                                            UINT16 latency, UINT16 timeout)
 {
     tL2C_LCB            *p_lcb;
     tACL_CONN           *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
@@ -135,7 +134,6 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int,
     p_lcb->latency = latency;
     p_lcb->timeout = timeout;
     p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
-    p_lcb->p_conn_param_update_cb = p_callback;
 
     l2cble_start_conn_update(p_lcb);
 
@@ -237,42 +235,6 @@ UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
     return reason;
 }
 
-void l2cble_use_preferred_conn_params(BD_ADDR bda) {
-    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
-    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
-
-    /* If there are any preferred connection parameters, set them now */
-    if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
-         (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
-         (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
-         (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
-         (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
-         (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
-         (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
-         ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int &&
-          p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
-          (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) ||
-          (p_lcb->latency > p_dev_rec->conn_params.slave_latency) ||
-          (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout)))
-    {
-        L2CAP_TRACE_DEBUG ("%s: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", __func__,
-                            p_lcb->handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
-                            p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
-
-        p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
-        p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
-        p_lcb->timeout      = p_dev_rec->conn_params.supervision_tout;
-        p_lcb->latency      = p_dev_rec->conn_params.slave_latency;
-
-        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
-                                           p_dev_rec->conn_params.min_conn_int,
-                                           p_dev_rec->conn_params.max_conn_int,
-                                           p_dev_rec->conn_params.slave_latency,
-                                           p_dev_rec->conn_params.supervision_tout,
-                                           0, 0);
-    }
-}
-
 /*******************************************************************************
 **
 ** Function l2cble_notify_le_connection
@@ -305,8 +267,6 @@ void l2cble_notify_le_connection (BD_ADDR bda)
                 l2c_csm_execute (p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
         }
     }
-
-    l2cble_use_preferred_conn_params(bda);
 }
 
 /*******************************************************************************
@@ -505,6 +465,7 @@ void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE typ
 *******************************************************************************/
 static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
 {
+    UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
     tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
 
     // TODO(armansito): The return value of this call wasn't being used but the
@@ -516,7 +477,6 @@ static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
 
     if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
     {
-        UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
         /* application requests to disable parameters update.
            If parameters are already updated, lets set them
            up to what has been requested during connection establishement */
@@ -565,12 +525,6 @@ static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
                 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
                     p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
                 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
-
-                /* Record the BLE connection update request if the role is master device */
-                bt_bdaddr_t bd_addr;
-                bdcpy(bd_addr.address, p_lcb->remote_bd_addr);
-                btif_debug_ble_connection_update_request(bd_addr, p_lcb->min_interval, p_lcb->max_interval,
-                    p_lcb->latency, p_lcb->timeout);
             }
             else
             {
@@ -579,10 +533,16 @@ static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
             }
             p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
             p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
-
-       }
+        }
     }
 
+    /* Record the BLE connection update request. */
+    if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) {
+      bt_bdaddr_t bd_addr;
+      bdcpy(bd_addr.address, p_lcb->remote_bd_addr);
+      btif_debug_ble_connection_update_request(bd_addr, min_conn_int, max_conn_int, slave_latency,
+          supervision_tout);
+    }
 }
 
 /*******************************************************************************
@@ -617,12 +577,6 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status,
 
     l2cble_start_conn_update(p_lcb);
 
-    /* Callback to upper layer */
-    if (p_lcb->p_conn_param_update_cb) {
-        p_lcb->p_conn_param_update_cb(p_lcb->remote_bd_addr, interval, latency,
-                                      timeout, status);
-    }
-
     /* Record the BLE connection update response. */
     bt_bdaddr_t bd_addr;
     bdcpy(bd_addr.address, p_lcb->remote_bd_addr);
index 0390be7..8af47d7 100644 (file)
@@ -441,7 +441,6 @@ typedef struct t_l2c_linkcb
     UINT16              latency;
     UINT16              timeout;
 
-    tBTA_DM_BLE_CONN_PARAM_CBACK *p_conn_param_update_cb;
 #endif
 
 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
@@ -683,7 +682,7 @@ extern BOOLEAN  l2cu_lcb_disconnecting (void);
 
 extern BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport);
 extern BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb);
-extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid);
+extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb);
 extern void    l2cu_resubmit_pending_sec_req (BD_ADDR p_bda);
 extern void    l2cu_initialize_amp_ccb (tL2C_LCB *p_lcb);
 extern void    l2cu_adjust_out_mps (tL2C_CCB *p_ccb);
index 7a50eb2..2fefd13 100644 (file)
@@ -45,7 +45,7 @@
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
-static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fixed_cid);
+static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf);
 
 /*******************************************************************************
 **
@@ -1065,7 +1065,6 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
 {
     int         xx;
     BOOLEAN     single_write = FALSE;
-    UINT16    fixed_cid;
 
     /* Save the channel ID for faster counting */
     if (p_buf)
@@ -1111,31 +1110,24 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
         /* Loop through, starting at the next */
         for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++)
         {
-            /* Check for wraparound */
-            if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
-                p_lcb = &l2cb.lcb_pool[0];
-
             /* If controller window is full, nothing to do */
-            if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
-                (l2cb.controller_xmit_window == 0 ||
-                 l2cb.round_robin_unacked >= l2cb.round_robin_quota))
-            {
+            if (((l2cb.controller_xmit_window == 0 ||
+                  (l2cb.round_robin_unacked >= l2cb.round_robin_quota))
 #if (BLE_INCLUDED == TRUE)
-                continue;
+                && (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+                )
+              || (p_lcb->transport == BT_TRANSPORT_LE &&
+                 (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota ||
+                  l2cb.controller_le_xmit_window == 0 )))
 #else
-                /* No more quota and only BR/EDR supported, so nothing more to do*/
-                break;
+                ))
 #endif
-            }
+            break;
 
-#if (BLE_INCLUDED == TRUE)
-            if (p_lcb->transport == BT_TRANSPORT_LE &&
-                (l2cb.controller_le_xmit_window == 0 ||
-                 l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota))
-            {
-                continue;
-            }
-#endif
+
+            /* Check for wraparound */
+            if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
+                p_lcb = &l2cb.lcb_pool[0];
 
             if ( (!p_lcb->in_use)
                || (p_lcb->partial_segment_being_sent)
@@ -1148,7 +1140,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
             if (!list_is_empty(p_lcb->link_xmit_data_q)) {
                 p_buf = (BT_HDR *)list_front(p_lcb->link_xmit_data_q);
                 list_remove(p_lcb->link_xmit_data_q, p_buf);
-                l2c_link_send_to_lower (p_lcb, p_buf, 0);
+                l2c_link_send_to_lower (p_lcb, p_buf);
             }
             else if (single_write)
             {
@@ -1156,9 +1148,9 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
                 break;
             }
             /* If nothing on the link queue, check the channel queue */
-            else if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb, &fixed_cid)) != NULL)
+            else if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb)) != NULL)
             {
-                l2c_link_send_to_lower (p_lcb, p_buf, fixed_cid);
+                l2c_link_send_to_lower (p_lcb, p_buf);
             }
         }
 
@@ -1201,7 +1193,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
 
             p_buf = (BT_HDR *)list_front(p_lcb->link_xmit_data_q);
             list_remove(p_lcb->link_xmit_data_q, p_buf);
-            if (!l2c_link_send_to_lower (p_lcb, p_buf, 0))
+            if (!l2c_link_send_to_lower (p_lcb, p_buf))
                 break;
         }
 
@@ -1216,10 +1208,10 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
             while ((l2cb.controller_xmit_window != 0) && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota))
 #endif
             {
-                if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb, &fixed_cid)) == NULL)
+                if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb)) == NULL)
                     break;
 
-                if (!l2c_link_send_to_lower (p_lcb, p_buf, fixed_cid))
+                if (!l2c_link_send_to_lower (p_lcb, p_buf))
                     break;
             }
         }
@@ -1245,7 +1237,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
 ** Returns          TRUE for success, FALSE for fail
 **
 *******************************************************************************/
-static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fixed_cid)
+static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf)
 {
     UINT16      num_segs;
     UINT16      xmit_window, acl_data_size;
@@ -1376,15 +1368,6 @@ static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fi
     }
 #endif
 
-    if (fixed_cid != 0)
-    {
-        L2CAP_TRACE_DEBUG("%s: fixed_cid = %d, send tx complete", __func__, fixed_cid);
-        /* send tx complete */
-        if (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedTxComplete_Cb)
-        {
-            (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedTxComplete_Cb)(fixed_cid, 1);
-        }
-    }
     return TRUE;
 }
 
index 77d6e1c..72bd52e 100644 (file)
@@ -1748,12 +1748,6 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb)
     {
         if (!p_lcb->ccb_queue.p_first_ccb)
         {
-            // Closing a security channel on LE device should not start connection
-            // timeout
-            if (p_lcb->transport == BT_TRANSPORT_LE &&
-                p_ccb->local_cid == L2CAP_SMP_CID)
-                return;
-
             l2cu_no_dynamic_ccbs (p_lcb);
         }
         else
@@ -3541,7 +3535,7 @@ static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
 ** Returns          pointer to buffer or NULL
 **
 *******************************************************************************/
-BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid)
+BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
 {
     tL2C_CCB    *p_ccb;
     BT_HDR      *p_buf;
@@ -3550,7 +3544,6 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid)
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
     int         xx;
 
-    *fixed_cid = 0;
     for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
     {
         if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL)
@@ -3590,11 +3583,9 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid)
                     L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
                     return (NULL);
                 }
-                if (fixed_cid != NULL)
-                {
-                    *fixed_cid = p_ccb->local_cid;
-                    L2CAP_TRACE_DEBUG("l2cu_get_buffer_to_send: fixed_cid = %d", *fixed_cid);
-                }
+                /* send tx complete */
+                if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
+                    (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
 
                 l2cu_check_channel_congestion (p_ccb);
                 l2cu_set_acl_hci_header (p_buf, p_ccb);
index 0eb5333..d2bbc58 100644 (file)
@@ -413,10 +413,11 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
             SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
             cpy_len = rem_len;
         }
-#if (SDP_DEBUG_RAW == TRUE)
-        SDP_TRACE_WARNING("list_len :%d cpy_len:%d raw_size:%d raw_used:%d",
-            list_len, cpy_len, p_ccb->p_db->raw_size, p_ccb->p_db->raw_used);
-#endif
+        SDP_TRACE_WARNING(
+          "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
+          "raw_used:%d raw_data:%p",
+          __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
+          p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
         memcpy (&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
         p_ccb->p_db->raw_used += cpy_len;
     }