[automerger] DO NOT MERGE HID Host: Check L2CAP packet data length am: 4344cfb76a

Change-Id: Iabccbce010c9c418b63a638c8936cc8616799070
diff --git a/EventLogTags.logtags b/EventLogTags.logtags
new file mode 100644
index 0000000..32493d8
--- /dev/null
+++ b/EventLogTags.logtags
@@ -0,0 +1,37 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31.  (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_".  Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace.  Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+#    (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+#
+# TODO: generate ".java" and ".h" files with integer constants from this file.
+
+1010000 bt_hci_timeout (opcode|1)
+1010001 bt_config_source (opcode|1)
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
index 3d52cef..285a967 100644
--- a/bta/ag/bta_ag_act.c
+++ b/bta/ag/bta_ag_act.c
@@ -432,6 +432,9 @@
     p_scb->hsp_version = HSP_VERSION_1_2;
     bta_ag_at_reinit(&p_scb->at_cb);
 
+    memset(&(p_scb->peer_hf_indicators), 0, sizeof(p_scb->peer_hf_indicators));
+    memset(&(p_scb->local_hf_indicators), 0, sizeof(p_scb->local_hf_indicators));
+
     /* stop timers */
     alarm_cancel(p_scb->ring_timer);
 #if (BTM_WBS_INCLUDED == TRUE)
diff --git a/bta/ag/bta_ag_cfg.c b/bta/ag/bta_ag_cfg.c
index cfe298a..e5893e1 100644
--- a/bta/ag/bta_ag_cfg.c
+++ b/bta/ag/bta_ag_cfg.c
@@ -52,9 +52,24 @@
                                                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
 #endif
 
+#ifndef BTA_AG_BIND_INFO
+#define BTA_AG_BIND_INFO "(1)"
+#endif
+
+const tBTA_AG_HF_IND bta_ag_local_hf_ind_cfg[] =
+{
+    /* The first row contains the number of indicators. Need to be updated accordingly */
+    {BTA_AG_NUM_LOCAL_HF_IND,   0,  0,  0,  0},
+
+    {1,    1,   1,   0,    1},     /* Enhanced Driver Status, supported, enabled, range 0 ~ 1 */
+    {2,    1,   1,   0,    100}    /* Battery Level Status, supported, enabled, range 0 ~ 100 */
+};
+
 const tBTA_AG_CFG bta_ag_cfg =
 {
     BTA_AG_CIND_INFO,
+    BTA_AG_BIND_INFO,
+    BTA_AG_NUM_LOCAL_HF_IND,
     BTA_AG_CONN_TIMEOUT,
     BTA_AG_SCO_PKT_TYPES,
     BTA_AG_CHLD_VAL_ECC,
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
index 2ab9f51..110b531 100644
--- a/bta/ag/bta_ag_cmd.c
+++ b/bta/ag/bta_ag_cmd.c
@@ -111,6 +111,8 @@
     BTA_AG_HF_CMD_CBC,
     BTA_AG_HF_CMD_BCC,
     BTA_AG_HF_CMD_BCS,
+    BTA_AG_HF_CMD_BIND,
+    BTA_AG_HF_CMD_BIEV,
     BTA_AG_HF_CMD_BAC
 };
 
@@ -152,6 +154,8 @@
     {"+CBC",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   100},
     {"+BCC",    BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
     {"+BCS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
+    {"+BIND",   BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST , BTA_AG_AT_STR,   0,   0},
+    {"+BIEV",   BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
     {"+BAC",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
     {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
 };
@@ -194,6 +198,7 @@
     BTA_AG_RES_COPS,
     BTA_AG_RES_CMEE,
     BTA_AG_RES_BCS,
+    BTA_AG_RES_BIND,
     BTA_AG_RES_UNAT
 };
 
@@ -223,6 +228,7 @@
     {"+COPS: ", BTA_AG_RES_FMT_STR},
     {"+CME ERROR: ", BTA_AG_RES_FMT_INT},
     {"+BCS: ",  BTA_AG_RES_FMT_INT},
+    {"+BIND: ", BTA_AG_RES_FMT_STR},
     {"",        BTA_AG_RES_FMT_STR}
 };
 
@@ -268,6 +274,8 @@
     BTA_AG_AT_CBC_EVT,      /* BTA_AG_HF_CMD_CBC */
     0,                      /* BTA_AG_HF_CMD_BCC */
     BTA_AG_AT_BCS_EVT,      /* BTA_AG_HF_CMD_BCS */
+    BTA_AG_AT_BIND_EVT,     /* BTA_AG_HF_CMD_BIND */
+    BTA_AG_AT_BIEV_EVT,     /* BTA_AG_HF_CMD_BIEV */
     BTA_AG_AT_BAC_EVT       /* BTA_AG_HF_CMD_BAC */
 };
 
@@ -294,6 +302,7 @@
     0,                  /* BTA_AG_CALL_CANCEL_RES */
     0,                  /* BTA_AG_END_CALL_RES */
     0,                  /* BTA_AG_IN_CALL_HELD_RES */
+    BTA_AG_RES_BIND,    /* BTA_AG_BIND_RES */
     BTA_AG_RES_UNAT     /* BTA_AG_UNAT_RES */
 };
 
@@ -319,7 +328,8 @@
     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_OUT_CALL_CONN_RES */
     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_CALL_CANCEL_RES */
     BTA_AG_CALLSETUP_NONE,      /* BTA_AG_END_CALL_RES */
-    BTA_AG_CALLSETUP_NONE       /* BTA_AG_IN_CALL_HELD_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_IN_CALL_HELD_RES */
+    0                           /* BTA_AG_BIND_RES */
 };
 
 /*******************************************************************************
@@ -858,6 +868,222 @@
 
 /*******************************************************************************
 **
+** Function         bta_ag_find_empty_hf_ind)
+**
+** Description      This function returns the index of an empty HF indicator
+**                  structure.
+**
+** Returns          int : index of the empty HF indicator structure or
+**                            -1 if no empty indicator
+**                            is available.
+**
+*******************************************************************************/
+static int bta_ag_find_empty_hf_ind(tBTA_AG_SCB *p_scb)
+{
+    for (int index = 0; index < BTA_AG_MAX_NUM_PEER_HF_IND; index++)
+    {
+        if (p_scb->peer_hf_indicators[index].ind_id == 0)
+            return index;
+    }
+
+    return -1;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_ag_find_hf_ind_by_id
+**
+** Description      This function returns the index of the HF indicator
+**                  structure by the indicator id
+**
+** Returns          int : index of the HF indicator structure
+**                            -1 if the indicator
+**                            was not found.
+**
+*******************************************************************************/
+static int bta_ag_find_hf_ind_by_id(tBTA_AG_HF_IND *p_hf_ind, int size, uint32_t ind_id)
+{
+    for (int index = 0; index < size; index++)
+    {
+        if (p_hf_ind[index].ind_id == ind_id)
+            return index;
+    }
+
+    return -1;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_parse_bind_set
+**
+** Description      Parse AT+BIND set command and save the indicators
+**
+** Returns          true if successful
+**
+*******************************************************************************/
+static bool bta_ag_parse_bind_set(tBTA_AG_SCB *p_scb, tBTA_AG_VAL val)
+{
+    char *p_token = strtok(val.str, ",");
+    if (p_token == NULL)
+        return false;
+
+    while (p_token != NULL)
+    {
+        uint16_t rcv_ind_id = atoi(p_token);
+        int index = bta_ag_find_empty_hf_ind(p_scb);
+        if (index == -1)
+        {
+            APPL_TRACE_WARNING("%s Can't save more indicators", __func__);
+            return false;
+        }
+
+        p_scb->peer_hf_indicators[index].ind_id = rcv_ind_id;
+        APPL_TRACE_DEBUG("%s peer_hf_ind[%d] = %d", __func__, index, rcv_ind_id);
+
+        p_token = strtok(NULL, ",");
+    }
+
+    return true;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_bind_response
+**
+** Description      Send response for the AT+BIND command (HFP 1.7) received
+**                  from the headset based on the argument types.
+**
+** Returns          Void
+**
+*******************************************************************************/
+static void bta_ag_bind_response(tBTA_AG_SCB *p_scb, uint8_t arg_type)
+{
+    char buffer[BTA_AG_AT_MAX_LEN];
+    memset(buffer, 0, BTA_AG_AT_MAX_LEN);
+
+    if (arg_type == BTA_AG_AT_TEST)
+    {
+        int index = 0;
+        buffer[index++] = '(';
+
+        for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++)
+        {
+            if (bta_ag_local_hf_ind_cfg[i+1].is_supported == true)
+            {
+                /* Add ',' from second indicator */
+                if (index > 1)
+                    buffer[index++] = ',';
+                sprintf(&buffer[index++], "%d", bta_ag_local_hf_ind_cfg[i+1].ind_id);
+            }
+        }
+
+        buffer[index++] = ')';
+
+        bta_ag_send_result(p_scb, BTA_AG_RES_BIND, buffer, 0);
+        bta_ag_send_ok(p_scb);
+    }
+    else if (arg_type == BTA_AG_AT_READ)
+    {
+        char *p = buffer;
+
+        /* bta_ag_local_hf_ind_cfg[0].ind_id is used as BTA_AG_NUM_LOCAL_HF_IND */
+        for (uint32_t i = 0; i < bta_ag_local_hf_ind_cfg[0].ind_id; i++)
+        {
+            if (i == BTA_AG_MAX_NUM_LOCAL_HF_IND)
+            {
+                APPL_TRACE_WARNING("%s No space for more HF indicators", __func__);
+                break;
+            }
+
+            p_scb->local_hf_indicators[i].ind_id = bta_ag_local_hf_ind_cfg[i+1].ind_id;
+            p_scb->local_hf_indicators[i].is_supported = bta_ag_local_hf_ind_cfg[i+1].is_supported;
+            p_scb->local_hf_indicators[i].is_enable = bta_ag_local_hf_ind_cfg[i+1].is_enable;
+
+            int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators,
+                                                    BTA_AG_MAX_NUM_PEER_HF_IND,
+                                                    p_scb->local_hf_indicators[i].ind_id);
+
+            /* Check whether local and peer sides support this indicator */
+            if (p_scb->local_hf_indicators[i].is_supported == true && peer_index != -1)
+            {
+                /* In the format of ind, state */
+                p += utl_itoa((uint16_t) p_scb->local_hf_indicators[i].ind_id, p);
+                *p++ = ',';
+                p += utl_itoa((uint16_t) p_scb->local_hf_indicators[i].is_enable, p);
+
+                bta_ag_send_result(p_scb, BTA_AG_RES_BIND, buffer, 0);
+
+                memset(buffer, 0, sizeof(buffer));
+                p = buffer;
+            } else {
+                /* If indicator is not supported, also set it to disable */
+                p_scb->local_hf_indicators[i].is_enable = false;
+            }
+        }
+
+        bta_ag_send_ok(p_scb);
+
+        /* If the service level connection wan't already open, now it's open */
+        if (!p_scb->svc_conn)
+            bta_ag_svc_conn_open(p_scb, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_parse_biev_response
+**
+** Description      Send response for AT+BIEV command (HFP 1.7) received from
+**                  the headset based on the argument types.
+**
+** Returns          true if the response was parsed successfully
+**
+*******************************************************************************/
+static bool bta_ag_parse_biev_response(tBTA_AG_SCB *p_scb, tBTA_AG_VAL *val)
+{
+    char *p_token = strtok(val->str, ",");
+    uint16_t rcv_ind_id = atoi(p_token);
+
+    p_token = strtok(NULL, ",");
+    uint16_t rcv_ind_val = atoi(p_token);
+
+    APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id, rcv_ind_val);
+
+    /* Check whether indicator ID is valid or not */
+    if (rcv_ind_id > BTA_AG_NUM_LOCAL_HF_IND)
+    {
+        APPL_TRACE_WARNING("%s received invalid indicator id %d", __func__, rcv_ind_id);
+        return false;
+    }
+
+    /* Check this indicator is support or not and enabled or not */
+    int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators,
+                                BTA_AG_MAX_NUM_LOCAL_HF_IND, rcv_ind_id);
+    if (local_index == -1 ||
+        p_scb->local_hf_indicators[local_index].is_supported != true ||
+        p_scb->local_hf_indicators[local_index].is_enable != true)
+    {
+        APPL_TRACE_WARNING("%s indicator id %d not supported or disabled", __func__, rcv_ind_id);
+        return false;
+    }
+
+    /* For each indicator ID, check whether the indicator value is in range */
+    if (rcv_ind_val < bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_min_val ||
+        rcv_ind_val > bta_ag_local_hf_ind_cfg[rcv_ind_id].ind_max_val)
+    {
+        APPL_TRACE_WARNING("%s invalid ind_val %d", __func__, rcv_ind_val);
+        return false;
+    }
+
+    val->lidx = rcv_ind_id;
+    val->num = rcv_ind_val;
+
+    return true;
+}
+
+/*******************************************************************************
+**
 ** Function         bta_ag_at_hfp_cback
 **
 ** Description      AT command processing callback for HFP.
@@ -889,6 +1115,7 @@
 
     val.hdr.handle = bta_ag_scb_to_idx(p_scb);
     val.hdr.app_id = p_scb->app_id;
+    val.hdr.status = BTA_AG_SUCCESS;
     val.num = int_arg;
     bdcpy(val.bd_addr, p_scb->peer_addr);
     strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
@@ -1017,6 +1244,37 @@
             }
             break;
 
+        case BTA_AG_HF_CMD_BIND:
+            APPL_TRACE_DEBUG("%s BTA_AG_HF_CMD_BIND arg_type: %d", __func__, arg_type);
+            if (arg_type == BTA_AG_AT_SET)
+            {
+                if (bta_ag_parse_bind_set(p_scb, val))
+                {
+                    bta_ag_send_ok(p_scb);
+                } else {
+                    event = 0;/* don't call callback */
+                    bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
+                }
+            } else {
+                bta_ag_bind_response(p_scb, arg_type);
+
+                /* Need not pass this command beyond BTIF.*/
+                /* Stack handles it internally */
+                event = 0;/* don't call callback */
+            }
+            break;
+
+        case BTA_AG_HF_CMD_BIEV:
+            if (bta_ag_parse_biev_response(p_scb, &val))
+            {
+                bta_ag_send_ok(p_scb);
+            } else {
+                bta_ag_send_error(p_scb, BTA_AG_ERR_INVALID_INDEX);
+                /* don't call callback receiving invalid indicator */
+                event = 0;
+            }
+            break;
+
         case BTA_AG_HF_CMD_CIND:
             if (arg_type == BTA_AG_AT_TEST)
             {
@@ -1089,7 +1347,12 @@
 
         case BTA_AG_HF_CMD_BRSF:
             /* store peer features */
-            p_scb->peer_features = (UINT16) int_arg;
+            p_scb->peer_features = (uint16_t) int_arg;
+#if (BTA_HFP_VERSION < HFP_VERSION_1_7 || BTA_HFP_HF_IND_SUPPORTED != true)
+            p_scb->features &= ~BTA_AG_FEAT_HF_IND;
+#endif
+            APPL_TRACE_DEBUG("%s BRSF HF: 0x%x, phone: 0x%x", __func__,
+                p_scb->peer_features, p_scb->features);
 
             /* send BRSF, send OK */
             bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
@@ -1317,6 +1580,7 @@
     {
         val.hdr.handle = bta_ag_scb_to_idx(p_scb);
         val.hdr.app_id = p_scb->app_id;
+        val.hdr.status = BTA_AG_SUCCESS;
         val.num = 0;
         strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
         (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
@@ -1452,7 +1716,6 @@
 void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
 {
     UINT8 code = bta_ag_trans_result[p_result->result];
-
     APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
 
     switch(p_result->result)
@@ -1709,12 +1972,53 @@
             }
             break;
 
-       default:
+        case BTA_AG_BIND_RES:
+        {
+            /* Find whether ind_id is supported by local device or not */
+            int local_index = bta_ag_find_hf_ind_by_id(p_scb->local_hf_indicators,
+                                      BTA_AG_MAX_NUM_LOCAL_HF_IND, p_result->data.ind.id);
+            if (local_index == -1)
+            {
+                APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
+                    p_result->data.ind.id);
+                return;
+            }
+
+            /* Find whether ind_id is supported by peer device or not */
+            int peer_index = bta_ag_find_hf_ind_by_id(p_scb->peer_hf_indicators,
+                                      BTA_AG_MAX_NUM_PEER_HF_IND, p_result->data.ind.id);
+            if (peer_index == -1)
+            {
+                APPL_TRACE_WARNING("%s Invalid HF Indicator ID %d", __func__,
+                    p_result->data.ind.id);
+                return;
+            } else {
+                /* If the current state is different from the one upper layer request
+                   change current state and send out the result */
+                if (p_scb->local_hf_indicators[local_index].is_enable != p_result->data.ind.on_demand)
+                {
+                    char buffer[BTA_AG_AT_MAX_LEN] = {0};
+                    char *p = buffer;
+
+                    p_scb->local_hf_indicators[local_index].is_enable = p_result->data.ind.on_demand;
+                    p += utl_itoa(p_result->data.ind.id, p);
+                    *p++ = ',';
+                    p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p);
+
+                    bta_ag_send_result(p_scb, code, buffer, 0);
+                } else {
+                    APPL_TRACE_DEBUG("%s HF Indicator %d already %s", p_result->data.ind.id,
+                        (p_result->data.ind.on_demand == true) ? "Enabled" : "Disabled");
+                }
+            }
+            break;
+        }
+
+        default:
             break;
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_ag_result
diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h
index a95f0a8..b721ac0 100644
--- a/bta/ag/bta_ag_int.h
+++ b/bta/ag/bta_ag_int.h
@@ -42,13 +42,6 @@
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
-#define HFP_VERSION_1_1         0x0101
-#define HFP_VERSION_1_5         0x0105
-#define HFP_VERSION_1_6         0x0106
-
-#define HSP_VERSION_1_0         0x0100
-#define HSP_VERSION_1_2         0x0102
-
 /* Number of SCBs (AG service instances that can be registered) */
 #ifndef BTA_AG_NUM_SCB
 #define BTA_AG_NUM_SCB          2
@@ -62,6 +55,10 @@
 /* RFCOMM MTU SIZE */
 #define BTA_AG_MTU              256
 
+/* Max number of peer and local HF indicators */
+#define BTA_AG_MAX_NUM_PEER_HF_IND     20
+#define BTA_AG_MAX_NUM_LOCAL_HF_IND    4
+
 /* Internal profile indexes */
 #define BTA_AG_HSP              0       /* index for HSP */
 #define BTA_AG_HFP              1       /* index for HFP */
@@ -77,6 +74,7 @@
                                       BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT  | \
                                       BTA_AG_FEAT_ECS  | BTA_AG_FEAT_ECC     | \
                                       BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
+                                      BTA_AG_FEAT_HF_IND | BTA_AG_FEAT_ESCO  | \
                                       BTA_AG_FEAT_VOIP)
 
 #define BTA_AG_SDP_FEAT_SPEC         (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR    | \
@@ -298,6 +296,10 @@
     tBTA_AG_SCO_MSBC_SETTINGS codec_msbc_settings; /* settings to be used for the impending eSCO */
 #endif
 
+    tBTA_AG_HF_IND      peer_hf_indicators[BTA_AG_MAX_NUM_PEER_HF_IND];   /* Peer supported
+                                                                      HF indicators */
+    tBTA_AG_HF_IND      local_hf_indicators[BTA_AG_MAX_NUM_LOCAL_HF_IND]; /* Local supported
+                                                                      HF indicators */
 } tBTA_AG_SCB;
 
 /* type for sco data */
@@ -342,6 +344,7 @@
 
 /* config struct */
 extern tBTA_AG_CFG *p_bta_ag_cfg;
+extern tBTA_AG_HF_IND bta_ag_local_hf_ind_cfg[];
 
 /*****************************************************************************
 **  Function prototypes
diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c
index 2a5341b..89e6f6c 100644
--- a/bta/ag/bta_ag_sco.c
+++ b/bta/ag/bta_ag_sco.c
@@ -84,9 +84,9 @@
     {
         BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
         BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
-        0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+        0x000c,                             /* 12 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
         BTM_VOICE_SETTING_CVSD,             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
-       (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
+       (BTM_SCO_PKT_TYPES_MASK_HV1      +   /* Packet Types                             */
         BTM_SCO_PKT_TYPES_MASK_HV2      +
         BTM_SCO_PKT_TYPES_MASK_HV3      +
         BTM_SCO_PKT_TYPES_MASK_EV3      +
@@ -94,7 +94,7 @@
         BTM_SCO_PKT_TYPES_MASK_EV5      +
         BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
         BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
-        BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
+        BTM_ESCO_RETRANS_QUALITY            /* Retransmission effort                    */
     },
     /* mSBC  T1 */
     {
@@ -1575,9 +1575,9 @@
         {
             resp.rx_bw = BTM_64KBITS_RATE;
             resp.tx_bw = BTM_64KBITS_RATE;
-            resp.max_latency = 10;
+            resp.max_latency = 12;
             resp.voice_contfmt = 0x60;
-            resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
+            resp.retrans_effort = BTM_ESCO_RETRANS_QUALITY;
 
             if (p_data->link_type == BTM_LINK_TYPE_SCO)
             {
diff --git a/bta/ag/bta_ag_sdp.c b/bta/ag/bta_ag_sdp.c
index cb5bd80..aa43c02 100644
--- a/bta/ag/bta_ag_sdp.c
+++ b/bta/ag/bta_ag_sdp.c
@@ -159,7 +159,7 @@
     if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE)
     {
         profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
-        version = HFP_VERSION_1_6;
+        version = BTA_HFP_VERSION;
     }
     else
     {
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c
index 6c5d874..1e73fa6 100644
--- a/bta/av/bta_av_aact.c
+++ b/bta/av/bta_av_aact.c
@@ -1567,7 +1567,10 @@
     {
         /* SNK initiated L2C connection while SRC was doing SDP.    */
         /* Wait until timeout to check if SNK starts signalling.    */
-        APPL_TRACE_EVENT("bta_av_connect_req: coll_mask = 0x%2X", p_scb->coll_mask);
+        APPL_TRACE_EVENT("%s: coll_mask = 0x%2X", __func__, p_scb->coll_mask);
+        p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
+        APPL_TRACE_EVENT("%s: updated coll_mask = 0x%2X", __func__,
+                         p_scb->coll_mask);
         return;
     }
 
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index 5857dd6..9cc802f 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -1613,6 +1613,8 @@
 
             if (bta_av_is_scb_opening(p_scb))
             {
+                APPL_TRACE_DEBUG("%s: stream state opening: SDP started = %d",
+                                 __func__, p_scb->sdp_discovery_started);
                 if (p_scb->sdp_discovery_started)
                 {
                     /* We are still doing SDP. Run the timer again. */
@@ -1634,6 +1636,7 @@
             {
                 /* Stay in incoming state if SNK does not start signalling */
 
+                APPL_TRACE_DEBUG("%s: stream state incoming", __func__);
                 /* API open was called right after SNK opened L2C connection. */
                 if (p_scb->coll_mask & BTA_AV_COLL_API_CALLED)
                 {
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index bb8e0b5..e156465 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -4425,7 +4425,6 @@
             else
             {
                 sec_event.auth_cmpl.success = TRUE;
-                /* We also register for Service Changed right after connect. */
                 if (!p_data->complt.smp_over_br)
                     GATT_ConfigServiceChangeCCC(bda, TRUE, BT_TRANSPORT_LE);
             }
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 388d9a4..01b06b8 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -518,7 +518,7 @@
 
     /* open/hold a connection */
     if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda,
-                      TRUE, p_data->api_conn.transport))
+                      true, p_data->api_conn.transport, false))
     {
         APPL_TRACE_ERROR("Connection open failure");
 
@@ -558,7 +558,7 @@
     if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))
     {
         /* always call open to hold a connection */
-        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE, p_data->transport))
+        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, false, p_data->transport, false))
         {
             uint8_t *bda = (uint8_t *)p_data->remote_bda;
             status = BTA_GATT_ERROR;
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index 4c35b0c..3f357bf 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -689,7 +689,7 @@
     {
         /* should always get the connection ID */
         if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda,
-                        p_msg->api_open.is_direct, p_msg->api_open.transport))
+                        p_msg->api_open.is_direct, p_msg->api_open.transport, false))
         {
             status = BTA_GATT_OK;
 
diff --git a/bta/hh/bta_hh_le.c b/bta/hh/bta_hh_le.c
index e6f854f..92b3c40 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -802,7 +802,7 @@
                 if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
                     p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
                 {
-                    APPL_TRACE_DEBUG("---> Deregister Report ID: %d", p_rpt->rpt_id);
+                    APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__, p_rpt->rpt_id);
                     BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
                                                          p_rpt->char_inst_id);
                 }
@@ -810,7 +810,7 @@
                 else if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
                          p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
                 {
-                    APPL_TRACE_DEBUG("<--- Register Boot Report ID: %d", p_rpt->rpt_id);
+                    APPL_TRACE_DEBUG("%s <--- Register Boot Report ID: %d", __func__, p_rpt->rpt_id);
                     BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
                                                        p_rpt->char_inst_id);
                 }
@@ -822,14 +822,14 @@
                     p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
                 {
 
-                    APPL_TRACE_DEBUG("---> Deregister Boot Report ID: %d", p_rpt->rpt_id);
+                    APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__, p_rpt->rpt_id);
                     BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
                                                          p_rpt->char_inst_id);
                 }
                 else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
                          p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
                 {
-                    APPL_TRACE_DEBUG("<--- Register Report ID: %d", p_rpt->rpt_id);
+                    APPL_TRACE_DEBUG("%s <--- Register Report ID: %d", __func__, p_rpt->rpt_id);
                     BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
                                                        p_rpt->char_inst_id);
                 }
@@ -842,6 +842,41 @@
 
 /*******************************************************************************
 **
+** Function         bta_hh_le_deregister_input_notif
+**
+** Description      Deregister all notifications
+**
+*******************************************************************************/
+void bta_hh_le_deregister_input_notif(tBTA_HH_DEV_CB *p_dev_cb)
+{
+    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc.report[0];
+
+    for (UINT8 i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++)
+    {
+        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
+        {
+            if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
+                p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
+            {
+                APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__, p_rpt->rpt_id);
+                BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
+                                                    p_rpt->char_inst_id);
+            }
+            else if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
+                p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
+                p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
+            {
+                APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__, p_rpt->rpt_id);
+                BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
+                                                    p_rpt->char_inst_id);
+            }
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
 ** Function         bta_hh_le_open_cmpl
 **
 ** Description      HID over GATT connection sucessfully opened
@@ -2208,6 +2243,8 @@
 {
     tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
 
+    /* deregister all notification */
+    bta_hh_le_deregister_input_notif(p_cb);
     /* finaliza device driver */
     bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
     /* update total conn number */
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
index 0d7f7be..826adcd 100644
--- a/bta/hl/bta_hl_sdp.c
+++ b/bta/hl/bta_hl_sdp.c
@@ -179,7 +179,7 @@
     UINT8                           data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
     UINT8                           mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
     UINT16                          profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
-    UINT16                          version = BTA_HL_VERSION_01_00;
+    UINT16                          version = BTA_HL_VERSION;
     UINT8                           num_services=1;
     tBTA_HL_APP_CB                  *p_cb = BTA_HL_GET_APP_CB_PTR(0);
     BOOLEAN                         result = TRUE;
@@ -382,7 +382,7 @@
     UINT8                           data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
     UINT8                           mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
     UINT16                          profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
-    UINT16                          version = BTA_HL_VERSION_01_00;
+    UINT16                          version = BTA_HL_VERSION;
     UINT8                           num_services=1;
     tBTA_HL_APP_CB                  *p_cb = BTA_HL_GET_APP_CB_PTR(app_idx);
     BOOLEAN                         result = TRUE;
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index ff85c9b..fa76a57 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -30,6 +30,24 @@
 /*****************************************************************************
 **  Constants and data types
 *****************************************************************************/
+#define HFP_VERSION_1_1         0x0101
+#define HFP_VERSION_1_5         0x0105
+#define HFP_VERSION_1_6         0x0106
+#define HFP_VERSION_1_7         0x0107
+
+#define HSP_VERSION_1_0         0x0100
+#define HSP_VERSION_1_2         0x0102
+
+/* Note, if you change the default version here, please also change the one in
+ * bta_hs_api.h, they are meant to be the same.
+ */
+#ifndef BTA_HFP_VERSION
+#define BTA_HFP_VERSION         HFP_VERSION_1_7
+#endif
+
+#ifndef BTA_HFP_HF_IND_SUPPORTED
+#define BTA_HFP_HF_IND_SUPPORTED    TRUE
+#endif
 
 /* AG feature masks */
 #define BTA_AG_FEAT_3WAY    0x00000001   /* Three-way calling */
@@ -42,12 +60,15 @@
 #define BTA_AG_FEAT_ECC     0x00000080   /* Enhanced Call Control */
 #define BTA_AG_FEAT_EXTERR  0x00000100   /* Extended error codes */
 #define BTA_AG_FEAT_CODEC   0x00000200   /* Codec Negotiation */
-#define BTA_AG_FEAT_VOIP    0x00000400   /* VoIP call */
+#define BTA_AG_FEAT_HF_IND  0x00000400   /* HF Indicators */
+#define BTA_AG_FEAT_ESCO    0x00000800   /* eSCO S4 (and T2) setting supported */
+
 /* Proprietary features: using 31 ~ 16 bits */
 #define BTA_AG_FEAT_BTRH    0x00010000   /* CCAP incoming call hold */
 #define BTA_AG_FEAT_UNAT    0x00020000   /* Pass unknown AT commands to application */
 #define BTA_AG_FEAT_NOSCO   0x00040000   /* No SCO control performed by BTA AG */
 #define BTA_AG_FEAT_NO_ESCO 0x00080000   /* Do not allow or use eSCO */
+#define BTA_AG_FEAT_VOIP    0x00100000   /* VoIP call */
 
 typedef UINT32 tBTA_AG_FEAT;
 
@@ -63,6 +84,9 @@
 #define BTA_AG_FAIL_RFCOMM      2 /* Open failed due to RFCOMM */
 #define BTA_AG_FAIL_RESOURCES   3 /* out of resources failure  */
 
+/*Status to disallow passing AT Events after BTIF */
+
+#define BTA_AG_DISALLOW_AT      5
 typedef UINT8 tBTA_AG_STATUS;
 
 /* handle values used with BTA_AgResult */
@@ -73,6 +97,18 @@
  * SCO_NO_CHANGE is used for changing sco behavior
  * They donot interfere with each other
  */
+
+/* Number of supported HF indicators, there is one HF indicator so far i.e.
+                                                   enhanced driver status. */
+/* Number of supported HF indicators,
+   1 for Enhanced Safety Status
+   2 for Battery Level Status */
+#ifndef BTA_AG_NUM_LOCAL_HF_IND
+#define BTA_AG_NUM_LOCAL_HF_IND     2
+#endif
+
+
+
 #define BTA_AG_HANDLE_SCO_NO_CHANGE 0xFFFF
 
 /* AG result codes used with BTA_AgResult */
@@ -98,6 +134,7 @@
 #define BTA_AG_IN_CALL_HELD_RES     19  /* Incoming call held */
 #define BTA_AG_UNAT_RES             20  /* Response to unknown AT command event */
 #define BTA_AG_MULTI_CALL_RES       21  /* SLC at three way call */
+#define BTA_AG_BIND_RES             22  /* Activate/Deactivate HF indicator */
 
 typedef UINT8 tBTA_AG_RES;
 
@@ -110,9 +147,14 @@
 #define BTA_AG_PEER_FEAT_ECS        0x0020  /* Enhanced Call Status */
 #define BTA_AG_PEER_FEAT_ECC        0x0040  /* Enhanced Call Control */
 #define BTA_AG_PEER_FEAT_CODEC      0x0080  /* Codec Negotiation */
-#define BTA_AG_PEER_FEAT_VOIP       0x0100  /* VoIP call */
+#define BTA_AG_PEER_FEAT_HF_IND     0x0100   /* HF Indicators */
+#define BTA_AG_PEER_FEAT_ESCO       0x0200   /* eSCO S4 (and T2) setting supported */
 
-typedef UINT16 tBTA_AG_PEER_FEAT;
+/* Proprietary features: using bits after 12 */
+#define BTA_AG_PEER_FEAT_UNAT       0x1000   /* Pass unknown AT command responses to application */
+#define BTA_AG_PEER_FEAT_VOIP       0x2000  /* VoIP call */
+
+typedef uint16_t tBTA_AG_PEER_FEAT;
 
 /* HFP peer supported codec masks */
 // TODO(google) This should use common definitions
@@ -204,8 +246,9 @@
 /* data associated with BTA_AG_IND_RES */
 typedef struct
 {
-    UINT16          id;
-    UINT16          value;
+    uint16_t          id;
+    uint16_t          value;
+    bool              on_demand;
 } tBTA_AG_IND;
 
 /* data type for BTA_AgResult() */
@@ -254,6 +297,8 @@
 #define BTA_AG_AT_CBC_EVT       25 /* Battery Level report from HF */
 #define BTA_AG_AT_BAC_EVT       26 /* avablable codec */
 #define BTA_AG_AT_BCS_EVT       27 /* Codec select */
+#define BTA_AG_AT_BIND_EVT      28 /* HF indicator */
+#define BTA_AG_AT_BIEV_EVT      29 /* HF indicator updates from peer */
 
 typedef UINT8 tBTA_AG_EVT;
 
@@ -305,6 +350,7 @@
     char                str[BTA_AG_AT_MAX_LEN+1];
     UINT16              num;
     UINT8               idx;    /* call number used by CLCC and CHLD */
+    UINT16              lidx;    /* long index, ex, HF indicator */
 } tBTA_AG_VAL;
 
 /* union of data associated with AG callback */
@@ -368,12 +414,24 @@
 #define BTA_AG_BEARER_RES2          6   /* Reserved     */
 #define BTA_AG_BEARER_RES3          7   /* Reserved     */
 
+/* type for HF indicator */
+typedef struct
+{
+    UINT16          ind_id;
+    BOOLEAN         is_supported;
+    BOOLEAN         is_enable;
+    UINT32          ind_min_val;
+    UINT32          ind_max_val;
+} tBTA_AG_HF_IND;
+
 /* AG configuration structure */
 typedef struct
 {
     char         *cind_info;
-    INT32        conn_tout;
-    UINT16       sco_pkt_types;
+    char         *bind_info;
+    uint8_t        num_local_hf_ind;
+    int32_t        conn_tout;
+    uint16_t       sco_pkt_types;
     char         *chld_val_ecc;
     char         *chld_val;
 } tBTA_AG_CFG;
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index b305499..b20c271 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -614,8 +614,11 @@
 /* BLE related definition */
 
 #define BTA_DM_AUTH_FAIL_BASE                   (HCI_ERR_MAX_ERR + 10)
-#define BTA_DM_AUTH_CONVERT_SMP_CODE(x)        (BTA_DM_AUTH_FAIL_BASE + (x))
-#define BTA_DM_AUTH_SMP_PASSKEY_FAIL             BTA_DM_AUTH_CONVERT_SMP_CODE (SMP_PASSKEY_ENTRY_FAIL)
+
+/* Converts SMP error codes defined in smp_api.h to SMP auth fail reasons below. */
+#define BTA_DM_AUTH_CONVERT_SMP_CODE(x)         (BTA_DM_AUTH_FAIL_BASE + (x))
+
+#define BTA_DM_AUTH_SMP_PASSKEY_FAIL            (BTA_DM_AUTH_FAIL_BASE + SMP_PASSKEY_ENTRY_FAIL)
 #define BTA_DM_AUTH_SMP_OOB_FAIL                (BTA_DM_AUTH_FAIL_BASE + SMP_OOB_FAIL)
 #define BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL          (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_AUTH_FAIL)
 #define BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL      (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_VALUE_ERR)
@@ -632,6 +635,7 @@
 #define BTA_DM_AUTH_SMP_BUSY                    (BTA_DM_AUTH_FAIL_BASE + SMP_BUSY)
 #define BTA_DM_AUTH_SMP_ENC_FAIL                (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_FAIL)
 #define BTA_DM_AUTH_SMP_RSP_TIMEOUT             (BTA_DM_AUTH_FAIL_BASE + SMP_RSP_TIMEOUT)
+#define BTA_DM_AUTH_SMP_CONN_TOUT               (BTA_DM_AUTH_FAIL_BASE + SMP_CONN_TOUT)
 
 /* connection parameter boundary value and dummy value */
 #define BTA_DM_BLE_SCAN_INT_MIN          BTM_BLE_SCAN_INT_MIN
diff --git a/bta/include/bta_hl_api.h b/bta/include/bta_hl_api.h
index b8e2c9a..62388be 100644
--- a/bta/include/bta_hl_api.h
+++ b/bta/include/bta_hl_api.h
@@ -89,7 +89,7 @@
 #define BTA_HL_NUM_PROTO_ELEMS          2
 #endif
 
-#define BTA_HL_VERSION_01_00            0x0100
+#define BTA_HL_VERSION                  0x0101
 #define BTA_HL_NUM_ADD_PROTO_LISTS      1
 #define BTA_HL_NUM_ADD_PROTO_ELEMS      2
 #define BTA_HL_MDEP_SEQ_SIZE            20
diff --git a/btif/Android.mk b/btif/Android.mk
index 78a475b..eee76b9 100644
--- a/btif/Android.mk
+++ b/btif/Android.mk
@@ -23,7 +23,8 @@
 
 # HAL layer
 btifCommonSrc := \
-  src/bluetooth.c
+  src/bluetooth.c \
+  ../EventLogTags.logtags
 
 # BTIF implementation
 btifCommonSrc += \
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index 03ba842..f852d48 100644
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -1044,13 +1044,21 @@
 
 static void btif_av_handle_event(UINT16 event, char* p_param)
 {
+    BTIF_TRACE_EVENT("%s event:%s", __func__,
+                     dump_av_sm_event_name((btif_av_sm_event_t)event));
     switch(event)
     {
         case BTIF_AV_CLEANUP_REQ_EVT:
-            BTIF_TRACE_EVENT("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
             btif_a2dp_stop_media_task();
             break;
 
+        case BTA_AV_REGISTER_EVT:
+            if (btif_av_cb.sm_handle == NULL)
+            {
+                btif_av_cb.bta_handle = ((tBTA_AV*)p_param)->registr.hndl;
+                BTIF_TRACE_DEBUG("%s: BTA AV Handle updated", __func__);
+            }
+            /* FALLTHROUGH */
         default:
             btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);
             btif_av_event_free_data(event, p_param);
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c
index 24a8c17..d5fb323 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -52,6 +52,8 @@
 #include <cutils/properties.h>
 #endif  /* !defined(OS_GENERIC) */
 
+#define BT_CONFIG_SOURCE_TAG_NUM 1010001
+
 #define INFO_SECTION "Info"
 #define FILE_TIMESTAMP "TimeCreated"
 #define FILE_SOURCE "FileSource"
@@ -199,6 +201,8 @@
     goto error;
   }
 
+  LOG_EVENT_INT(BT_CONFIG_SOURCE_TAG_NUM, btif_config_source);
+
   pthread_mutex_unlock(&lock);
   return future_new_immediate(FUTURE_SUCCESS);
 
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index b1ad00b..49fa274 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -3086,6 +3086,8 @@
         {
             case BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL:
             case BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL:
+            case BTA_DM_AUTH_SMP_UNKNOWN_ERR:
+            case BTA_DM_AUTH_SMP_CONN_TOUT:
                 btif_dm_remove_ble_bonding_keys();
                 status = BT_STATUS_AUTH_FAILURE;
                 break;
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 57b5958..c70fa49 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -1023,6 +1023,9 @@
 
 static void btm_read_rssi_cb (tBTM_RSSI_RESULTS *p_result)
 {
+    if (!p_result)
+      return;
+
     btif_gattc_cb_t btif_cb;
 
     bdcpy(btif_cb.bd_addr.address, p_result->rem_bda);
diff --git a/btif/src/btif_gatt_test.c b/btif/src/btif_gatt_test.c
index 349674e..ab1c1d2 100644
--- a/btif/src/btif_gatt_test.c
+++ b/btif/src/btif_gatt_test.c
@@ -240,7 +240,7 @@
             if (params->u1 == BT_DEVICE_TYPE_BLE)
                 BTM_SecAddBleDevice(params->bda1->address, NULL, BT_DEVICE_TYPE_BLE, params->u2);
 
-            if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE, BT_TRANSPORT_LE) )
+            if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, true, BT_TRANSPORT_LE, false) )
             {
                 LOG_ERROR(LOG_TAG, "%s: GATT_Connect failed!", __FUNCTION__);
             }
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index 4987bbe..6abf099 100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -73,6 +73,8 @@
                              BTA_AG_FEAT_BTRH   | \
                              BTA_AG_FEAT_VREC   | \
                              BTA_AG_FEAT_CODEC |\
+                             BTA_AG_FEAT_HF_IND | \
+                             BTA_AG_FEAT_ESCO   | \
                              BTA_AG_FEAT_UNAT)
 #endif
 #else
@@ -84,6 +86,8 @@
                              BTA_AG_FEAT_EXTERR | \
                              BTA_AG_FEAT_BTRH   | \
                              BTA_AG_FEAT_VREC   | \
+                             BTA_AG_FEAT_HF_IND | \
+                             BTA_AG_FEAT_ESCO   | \
                              BTA_AG_FEAT_UNAT)
 #endif
 #endif
@@ -621,6 +625,21 @@
                         BTHF_WBS_YES : BTHF_WBS_NO, &btif_hf_cb[idx].connected_bda);
             break;
 
+        case BTA_AG_AT_BIND_EVT:
+            if (p_data->val.hdr.status == BTA_AG_SUCCESS)
+            {
+                HAL_CBACK(bt_hf_callbacks, bind_cb,p_data->val.str,
+                                                &btif_hf_cb[idx].connected_bda);
+            }
+            break;
+
+        case BTA_AG_AT_BIEV_EVT:
+            if (p_data->val.hdr.status == BTA_AG_SUCCESS)
+            {
+                HAL_CBACK(bt_hf_callbacks, biev_cb, (bthf_hf_ind_type_t)p_data->val.lidx, (int)p_data->val.num,
+                              &btif_hf_cb[idx].connected_bda);
+            }
+            break;
         default:
             BTIF_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
             break;
@@ -1107,6 +1126,33 @@
 
 /*******************************************************************************
 **
+** Function         bind_response
+**
+** Description      Send +BIND response
+**
+** Returns          bt_status_t
+**
+*******************************************************************************/
+static bt_status_t bind_response(bthf_hf_ind_type_t ind_id, bthf_hf_ind_status_t ind_status,
+                                 bt_bdaddr_t * bd_addr)
+{
+    CHECK_BTHF_INIT();
+
+    int index = btif_hf_idx_by_bdaddr(bd_addr);
+    if (!is_connected(bd_addr) || index == BTIF_HF_INVALID_IDX)
+        return BT_STATUS_FAIL;
+
+    tBTA_AG_RES_DATA ag_res;
+    memset(&ag_res, 0, sizeof(ag_res));
+    ag_res.ind.id = ind_id;
+    ag_res.ind.on_demand = (ind_status == BTHF_HF_IND_ENABLED);
+
+    BTA_AgResult(btif_hf_cb[index].handle, BTA_AG_BIND_RES, &ag_res);
+    return BT_STATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
 ** Function         formatted_at_response
 **
 ** Description      Pre-formatted AT response, typically in response to unknown AT cmd
@@ -1581,6 +1627,7 @@
     phone_state_change,
     cleanup,
     configure_wbs,
+    bind_response,
 };
 
 /*******************************************************************************
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 08af577..262bc53 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -492,6 +492,25 @@
     }
 }
 
+static void btm_read_rssi_cb(void *data)
+{
+    assert(data);
+
+    tBTM_RSSI_RESULTS *result = (tBTM_RSSI_RESULTS*)data;
+    if (result->status != BTM_SUCCESS)
+    {
+        LOG_ERROR(LOG_TAG, "%s unable to read remote RSSI (status %d)",
+            __func__, result->status);
+        return;
+    }
+
+    char temp_buffer[20] = {0};
+    LOG_WARN(LOG_TAG, "%s device: %s, rssi: %d", __func__,
+        bdaddr_to_string((bt_bdaddr_t *)result->rem_bda, temp_buffer,
+            sizeof(temp_buffer)),
+        result->rssi);
+}
+
 /*****************************************************************************
  **  A2DP CTRL PATH
  *****************************************************************************/
@@ -3096,13 +3115,19 @@
         APPL_TRACE_WARNING("%s() - TX queue buffer count %d/%d", __func__,
                            fixed_queue_length(btif_media_cb.TxAaQ),
                            MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ - nb_frame);
+        // Keep track of drop-outs
         btif_media_cb.stats.tx_queue_dropouts++;
         btif_media_cb.stats.tx_queue_last_dropouts_us = timestamp_us;
 
+        // Flush all queued buffers...
         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));
         }
+
+        // Request RSSI for log purposes if we had to flush buffers
+        bt_bdaddr_t peer_bda = btif_av_get_addr();
+        BTM_ReadRSSI(peer_bda.address, btm_read_rssi_cb);
     }
 
     // Transcode frame
diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c
index b79832b..28a2499 100644
--- a/btif/src/btif_rc.c
+++ b/btif/src/btif_rc.c
@@ -280,6 +280,7 @@
 #endif
 static void rc_start_play_status_timer(void);
 static bool absolute_volume_disabled(void);
+static char const* key_id_to_str(uint16_t id);
 
 /*****************************************************************************
 **  Static variables
@@ -332,7 +333,7 @@
         return;
     }
 
-    BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
+    LOG_INFO(LOG_TAG, "AVRCP: Send key %s (%d) fd=%d", key_id_to_str(key), pressed, fd);
     send_event(fd, EV_KEY, key, pressed);
     send_event(fd, EV_SYN, SYN_REPORT, 0);
 }
@@ -4257,3 +4258,11 @@
     }
     return false;
 }
+
+static char const* key_id_to_str(uint16_t id) {
+    for (int i = 0; key_map[i].name != NULL; i++) {
+        if (id == key_map[i].mapped_id)
+            return key_map[i].name;
+    }
+    return "UNKNOWN KEY";
+}
diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c
index f4cffcb..a8c58c9 100644
--- a/btif/src/btif_util.c
+++ b/btif/src/btif_util.c
@@ -306,6 +306,8 @@
         CASE_RETURN_STR(BTA_AG_AT_CBC_EVT)
         CASE_RETURN_STR(BTA_AG_AT_BAC_EVT)
         CASE_RETURN_STR(BTA_AG_AT_BCS_EVT)
+        CASE_RETURN_STR(BTA_AG_AT_BIND_EVT)
+        CASE_RETURN_STR(BTA_AG_AT_BIEV_EVT)
 
         default:
             return "UNKNOWN MSG ID";
diff --git a/hci/Android.mk b/hci/Android.mk
index 24e3d4d..0727100 100644
--- a/hci/Android.mk
+++ b/hci/Android.mk
@@ -19,7 +19,8 @@
     src/hci_packet_parser.c \
     src/low_power_manager.c \
     src/packet_fragmenter.c \
-    src/vendor.c
+    src/vendor.c \
+    ../EventLogTags.logtags
 
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/include \
diff --git a/hci/src/hci_layer.c b/hci/src/hci_layer.c
index d566141..3a45135 100644
--- a/hci/src/hci_layer.c
+++ b/hci/src/hci_layer.c
@@ -55,6 +55,8 @@
 #define PREAMBLE_BUFFER_SIZE 4 // max preamble size, ACL
 #define RETRIEVE_ACL_LENGTH(preamble) ((((preamble)[3]) << 8) | (preamble)[2])
 
+#define BT_HCI_TIMEOUT_TAG_NUM 1010000
+
 static const uint8_t preamble_sizes[] = {
   HCI_COMMAND_PREAMBLE_SIZE,
   HCI_ACL_PREAMBLE_SIZE,
@@ -534,6 +536,7 @@
     // We shouldn't try to recover the stack from this command timeout.
     // If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
     LOG_ERROR(LOG_TAG, "%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode);
+    LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, wait_entry->opcode);
   }
 
   LOG_ERROR(LOG_TAG, "%s restarting the bluetooth process.", __func__);
diff --git a/stack/avdt/avdt_msg.c b/stack/avdt/avdt_msg.c
index adc1ae7..9697a59 100644
--- a/stack/avdt/avdt_msg.c
+++ b/stack/avdt/avdt_msg.c
@@ -26,6 +26,7 @@
  *
  ******************************************************************************/
 
+#include <log/log.h>
 #include <string.h>
 #include "bt_types.h"
 #include "bt_target.h"
@@ -673,6 +674,11 @@
 
             case AVDT_CAT_PROTECT:
                 p_cfg->psc_mask &= ~AVDT_PSC_PROTECT;
+                if (p + elem_len > p_end) {
+                    err = AVDT_ERR_LENGTH;
+                    android_errorWriteLog(0x534e4554, "78288378");
+                    break;
+                }
                 if ((elem_len + protect_offset) < AVDT_PROTECT_SIZE)
                 {
                     p_cfg->num_protect++;
@@ -747,6 +753,11 @@
                 {
                     tmp = AVDT_CODEC_SIZE - 1;
                 }
+                if (p + tmp > p_end) {
+                    err = AVDT_ERR_LENGTH;
+                    android_errorWriteLog(0x534e4554, "78288378");
+                    break;
+                }
                 p_cfg->num_codec++;
                 p_cfg->codec_info[0] = elem_len;
                 memcpy(&p_cfg->codec_info[1], p, tmp);
diff --git a/stack/avrc/avrc_api.c b/stack/avrc/avrc_api.c
index 77ca7d4..e612031 100644
--- a/stack/avrc/avrc_api.c
+++ b/stack/avrc/avrc_api.c
@@ -316,15 +316,15 @@
 
     if (status != AVRC_STS_NO_ERROR)
     {
-        /* use the current GKI buffer to build/send the reject message */
-        p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
+        p_rsp = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
+        p_rsp->offset = p_pkt->offset;
+        p_data = (uint8_t*)(p_rsp + 1) + p_pkt->offset;
         *p_data++ = AVRC_RSP_REJ;
         p_data += AVRC_VENDOR_HDR_SIZE; /* pdu */
         *p_data++ = 0;                  /* pkt_type */
         UINT16_TO_BE_STREAM(p_data, 1); /* len */
         *p_data++ = status;             /* error code */
-        p_pkt->len = AVRC_VENDOR_HDR_SIZE + 5;
-        p_rsp = p_pkt;
+        p_rsp->len = AVRC_VENDOR_HDR_SIZE + 5;
     }
 
     return p_rsp;
@@ -472,6 +472,7 @@
             if (p_rsp)
             {
                 AVCT_MsgReq( handle, label, AVCT_RSP, p_rsp);
+                osi_free_and_reset((void **)pp_pkt);
                 drop_code = 3;
             }
             else if (p_msg->hdr.opcode == AVRC_OP_DROP)
diff --git a/stack/bnep/bnep_main.c b/stack/bnep/bnep_main.c
index ad1f59f..39a5a5f 100644
--- a/stack/bnep/bnep_main.c
+++ b/stack/bnep/bnep_main.c
@@ -483,6 +483,13 @@
     UINT16        protocol = 0;
     UINT8         *p_src_addr, *p_dst_addr;
 
+    if (rem_len == 0)
+    {
+        android_errorWriteLog(0x534e4554, "78286118");
+        osi_free(p_buf);
+        return;
+    }
+
 
     /* Find CCB based on CID */
     if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
@@ -529,23 +536,35 @@
             UINT16      org_len, new_len;
             /* parse the extension headers and process unknown control headers */
             org_len = rem_len;
-            new_len = 0;
             do {
-                if (org_len < 2) break;
+                if (org_len < 2) {
+                    android_errorWriteLog(0x534e4554, "67863755");
+                    break;
+                }
                 ext     = *p++;
                 length  = *p++;
-                p += length;
 
                 new_len = (length + 2);
-                if (new_len > org_len) break;
+                if (new_len > org_len) {
+                    android_errorWriteLog(0x534e4554, "67863755");
+                    break;
+                }
 
-                if ((!(ext & 0x7F)) && (*p > BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG))
-                    bnep_send_command_not_understood (p_bcb, *p);
+                if ((ext & 0x7F) == BNEP_EXTENSION_FILTER_CONTROL) {
+                    if (length == 0) {
+                        android_errorWriteLog(0x534e4554, "79164722");
+                        break;
+                    }
+                    if (*p > BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG) {
+                        bnep_send_command_not_understood(p_bcb, *p);
+                    }
+                }
+
+                p += length;
 
                 org_len -= new_len;
 
             } while (ext & 0x80);
-            android_errorWriteLog(0x534e4554, "67863755");
         }
 
         osi_free(p_buf);
@@ -595,14 +614,13 @@
             {
                 ext_type = *p++;
                 rem_len--;
-                android_errorWriteLog(0x534e4554, "69271284");
                 extension_present = ext_type >> 7;
                 ext_type &= 0x7F;
 
                 /* if unknown extension present stop processing */
-                if (ext_type)
-                    break;
+                if (ext_type != BNEP_EXTENSION_FILTER_CONTROL) break;
 
+                android_errorWriteLog(0x534e4554, "69271284");
                 p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
             }
         }
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index 8c374f9..4ceb640 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -34,6 +34,8 @@
 #include "btm_int.h"
 #include "hcidefs.h"
 #include "bt_utils.h"
+#include "device/include/controller.h"
+
 
 #if BTM_SCO_INCLUDED == TRUE
 
@@ -59,7 +61,7 @@
 {
     BTM_64KBITS_RATE,               /* TX Bandwidth (64 kbits/sec)              */
     BTM_64KBITS_RATE,               /* RX Bandwidth (64 kbits/sec)              */
-    0x000a,                         /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+    0x000c,                         /* 12 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
     0x0060,                         /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
     (BTM_SCO_PKT_TYPES_MASK_HV1 +   /* Packet Types                             */
      BTM_SCO_PKT_TYPES_MASK_HV2 +
@@ -67,7 +69,7 @@
      BTM_SCO_PKT_TYPES_MASK_EV3 +
      BTM_SCO_PKT_TYPES_MASK_EV4 +
      BTM_SCO_PKT_TYPES_MASK_EV5),
-     BTM_ESCO_RETRANS_POWER        /* Retransmission Effort (Power)   */
+   BTM_ESCO_RETRANS_QUALITY         /* Retransmission Effort */
 };
 
 /*******************************************************************************
@@ -668,7 +670,7 @@
                              btm_cb.btm_sco_pkt_types_supported);
 
             /* OR in any exception packet types */
-            if (btm_cb.sco_cb.desired_sco_mode == HCI_LINK_TYPE_ESCO)
+            if (controller_get_interface()->get_bt_version()->hci_version >= HCI_PROTO_VERSION_2_0)
             {
                 temp_pkt_types |= ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
                     (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index 9fa29e7..ade7a9b 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -1633,10 +1633,17 @@
     /* extract the HCI handle first */
     UINT8   status;
     UINT16  handle;
+    UINT16  interval;
+    UINT16  latency;
+    UINT16  timeout;
 
-    STREAM_TO_UINT8  (status, p);
-    STREAM_TO_UINT16 (handle, p);
-    l2cble_process_conn_update_evt(handle, status);
+    STREAM_TO_UINT8(status, p);
+    STREAM_TO_UINT16(handle, p);
+    STREAM_TO_UINT16(interval, p);
+    STREAM_TO_UINT16(latency, p);
+    STREAM_TO_UINT16(timeout, p);
+
+    l2cble_process_conn_update_evt(handle, status, interval, latency, timeout);
 }
 
 static void btu_ble_read_remote_feat_evt (UINT8 *p)
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index d92665a..e14b13e 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -708,7 +708,7 @@
         p_clcb->connected = TRUE;
 
     /* hold the link here */
-    if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
+    if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE, false))
         return started;
 
     /* enqueue the request */
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index b8c45d3..597dc63 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -1357,7 +1357,8 @@
 ** Returns          TRUE if connection started; FALSE if connection start failure.
 **
 *******************************************************************************/
-BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct, tBT_TRANSPORT transport)
+BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct,
+                      tBT_TRANSPORT transport, BOOLEAN opportunistic)
 {
     tGATT_REG    *p_reg;
     BOOLEAN status = FALSE;
@@ -1372,7 +1373,7 @@
     }
 
     if (is_direct)
-        status = gatt_act_connect (p_reg, bd_addr, transport);
+        status = gatt_act_connect (p_reg, bd_addr, transport, opportunistic);
     else
     {
         if (transport == BT_TRANSPORT_LE)
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 9a2c6fa..74f0f35 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -235,24 +235,26 @@
 {
     UNUSED(gatt_if);
 
-    GATT_TRACE_EVENT("%s: from %08x%04x connected:%d conn_id=%d reason = 0x%04x", __func__,
-                      (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
-                      (bda[4]<<8)+bda[5], connected, conn_id, reason);
+    GATT_TRACE_EVENT ("%s: from %08x%04x connected:%d conn_id=%d reason = 0x%04x", __FUNCTION__,
+                       (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
+                       (bda[4]<<8)+bda[5], connected, conn_id, reason);
 
     tGATT_PROFILE_CLCB *p_clcb = gatt_profile_find_clcb_by_bd_addr(bda, transport);
-    if (connected) {
-        if (p_clcb == NULL)
-            p_clcb = gatt_profile_clcb_alloc(conn_id, bda, transport);
+    if (p_clcb == NULL)
+        return;
 
-        if (p_clcb == NULL)
-            return;
-
+    if (connected)
+    {
+        p_clcb->conn_id = conn_id;
         p_clcb->connected = TRUE;
-        p_clcb->ccc_stage = GATT_SVC_CHANGED_SERVICE;
-        gatt_cl_start_config_ccc(p_clcb);
+
+        if (p_clcb->ccc_stage == GATT_SVC_CHANGED_CONNECTING)
+        {
+            p_clcb->ccc_stage ++;
+            gatt_cl_start_config_ccc(p_clcb);
+        }
     } else {
-        if (p_clcb != NULL)
-            gatt_profile_clcb_dealloc(p_clcb);
+        gatt_profile_clcb_dealloc(p_clcb);
     }
 }
 
@@ -455,7 +457,7 @@
         p_clcb->connected = TRUE;
     }
     /* hold the link here */
-    GATT_Connect(gatt_cb.gatt_if, remote_bda, TRUE, transport);
+    GATT_Connect(gatt_cb.gatt_if, remote_bda, TRUE, transport, true);
     p_clcb->ccc_stage = GATT_SVC_CHANGED_CONNECTING;
 
     if (!p_clcb->connected)
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index 433a2f1..e4cb58f 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -31,6 +31,7 @@
 #include "bt_common.h"
 #include "gatt_int.h"
 #include "l2c_int.h"
+#include "log/log.h"
 
 #define GATT_WRITE_LONG_HDR_SIZE    5 /* 1 opcode + 2 handle + 2 offset */
 #define GATT_READ_CHAR_VALUE_HDL    (GATT_READ_CHAR_VALUE | 0x80)
@@ -566,9 +567,24 @@
     UNUSED(len);
 
     GATT_TRACE_DEBUG("gatt_process_error_rsp ");
-    STREAM_TO_UINT8(opcode, p);
-    STREAM_TO_UINT16(handle, p);
-    STREAM_TO_UINT8(reason, p);
+
+    if (len < 4) {
+        android_errorWriteLog(0x534e4554, "79591688");
+        GATT_TRACE_ERROR("Error response too short");
+        // Specification does not clearly define what should happen if error
+        // response is too short. General rule in BT Spec 5.0 Vol 3, Part F 3.4.1.1
+        // is: "If an error code is received in the Error Response that is not
+        // understood by the client, for example an error code that was reserved for
+        // future use that is now being used in a future version of this
+        // specification, then the Error Response shall still be considered to state
+        // that the given request cannot be performed for an unknown reason."
+        opcode = handle = 0;
+        reason = 0x7F;
+    } else {
+        STREAM_TO_UINT8(opcode, p);
+        STREAM_TO_UINT16(handle, p);
+        STREAM_TO_UINT8(reason, p);
+    }
 
     if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
     {
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 56760e9..1f97cb7 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -532,7 +532,7 @@
 
 /* from gatt_main.c */
 extern BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb);
-extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport);
+extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport, bool opportunistic);
 extern BOOLEAN gatt_connect (BD_ADDR rem_bda,  tGATT_TCB *p_tcb, tBT_TRANSPORT transport);
 extern void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf);
 extern void gatt_update_app_use_link_flag ( tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link);
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index bda5b41..4f1568a 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -274,49 +274,25 @@
 **
 ** Description      Update the application use link status
 **
-** Returns          void.
+** Returns          true if any modifications are made, false otherwise.
 **
 *******************************************************************************/
-void gatt_update_app_hold_link_status (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
+BOOLEAN gatt_update_app_hold_link_status(tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
 {
-    UINT8 i;
-    BOOLEAN found=FALSE;
-
-    if (p_tcb == NULL)
-    {
-        GATT_TRACE_ERROR("gatt_update_app_hold_link_status p_tcb=NULL");
-        return;
-    }
-
-
-    for (i=0; i<GATT_MAX_APPS; i++)
-    {
-        if (p_tcb->app_hold_link[i] ==  gatt_if)
-        {
-            found = TRUE;
-            if (!is_add)
-            {
-                p_tcb->app_hold_link[i] = 0;
-                break;
-            }
+    for (int i=0; i<GATT_MAX_APPS; i++) {
+        if (p_tcb->app_hold_link[i] == 0 && is_add) {
+            p_tcb->app_hold_link[i] = gatt_if;
+            GATT_TRACE_DEBUG("%s: added gatt_if=%d idx=%d ", __func__, gatt_if, i);
+            return TRUE;
+        } else if (p_tcb->app_hold_link[i] == gatt_if && !is_add) {
+            p_tcb->app_hold_link[i] = 0;
+            GATT_TRACE_DEBUG("%s: removed gatt_if=%d idx=%d", __func__, gatt_if, i);
+            return TRUE;
         }
     }
 
-    if (!found && is_add)
-    {
-        for (i=0; i<GATT_MAX_APPS; i++)
-        {
-            if (p_tcb->app_hold_link[i] ==  0)
-            {
-                p_tcb->app_hold_link[i] = gatt_if;
-                found = TRUE;
-                break;
-            }
-        }
-    }
-
-    GATT_TRACE_DEBUG("gatt_update_app_hold_link_status found=%d[1-found] idx=%d gatt_if=%d is_add=%d", found, i, gatt_if, is_add);
-
+    GATT_TRACE_DEBUG("%s: gatt_if=%d not found; is_add=%d", __func__, gatt_if, is_add);
+    return FALSE;
 }
 
 /*******************************************************************************
@@ -329,34 +305,37 @@
 ** Returns          void.
 **
 *******************************************************************************/
-void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link)
+void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add,
+                                   BOOLEAN check_acl_link)
 {
-    GATT_TRACE_DEBUG("gatt_update_app_use_link_flag  is_add=%d chk_link=%d",
-                      is_add, check_acl_link);
+    GATT_TRACE_DEBUG("%s: is_add=%d chk_link=%d", __func__, is_add, check_acl_link);
 
-    gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add);
+    if (!p_tcb)
+        return;
 
-    if (check_acl_link &&
-        p_tcb &&
-         p_tcb->att_lcid == L2CAP_ATT_CID && /* only update link idle timer for fixed channel */
-        (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) != GATT_INVALID_ACL_HANDLE))
-    {
-        if (is_add)
-        {
-            GATT_TRACE_DEBUG("GATT disables link idle timer");
-            /* acl link is connected disable the idle timeout */
-            GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
-        }
-        else
-        {
-            if (!gatt_num_apps_hold_link(p_tcb))
-            {
-                /* acl link is connected but no application needs to use the link
-                   so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
-                GATT_TRACE_DEBUG("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
-                GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport);
-            }
+    // If we make no modification, i.e. kill app that was never connected to a device,
+    // skip updating the device state.
+    if (!gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add))
+        return;
 
+    if (!check_acl_link ||
+            p_tcb->att_lcid != L2CAP_ATT_CID || /* only update link idle timer for fixed channel */
+            (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) == GATT_INVALID_ACL_HANDLE)) {
+        return;
+    }
+
+    if (is_add) {
+        GATT_TRACE_DEBUG("%s: disable link idle timer", __func__);
+        /* acl link is connected disable the idle timeout */
+        GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
+    } else {
+        if (!gatt_num_apps_hold_link(p_tcb)) {
+            /* acl link is connected but no application needs to use the link
+               so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
+            GATT_TRACE_DEBUG("%s: start link idle timer =%d sec", __func__,
+                             GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
+            GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
+                                p_tcb->transport);
         }
     }
 }
@@ -370,7 +349,8 @@
 ** Returns          void.
 **
 *******************************************************************************/
-BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport)
+BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr,
+                          tBT_TRANSPORT transport, BOOLEAN opportunistic)
 {
     BOOLEAN     ret = FALSE;
     tGATT_TCB   *p_tcb;
@@ -403,7 +383,6 @@
                 GATT_TRACE_ERROR("gatt_connect failed");
                 fixed_queue_free(p_tcb->pending_enc_clcb, NULL);
                 fixed_queue_free(p_tcb->pending_ind_q, NULL);
-                fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
                 memset(p_tcb, 0, sizeof(tGATT_TCB));
             }
             else
@@ -418,7 +397,11 @@
 
     if (ret)
     {
-        gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
+        if (!opportunistic)
+            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__);
     }
 
     return ret;
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index f1fcea7..e159bae 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -123,13 +123,16 @@
                                        tGATTS_RSP *p_msg, UINT16 mtu)
 {
     UINT16          ii, total_len, len;
-    BT_HDR          *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP));
     UINT8           *p;
     BOOLEAN         is_overflow = FALSE;
 
-    GATT_TRACE_DEBUG ("process_read_multi_rsp status=%d mtu=%d", status, mtu);
+    GATT_TRACE_DEBUG ("%s status=%d mtu=%d", __func__, status, mtu);
+
+    if (p_cmd->multi_rsp_q == NULL)
+        p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX);
 
     /* Enqueue the response */
+    BT_HDR  *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP));
     memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP));
     fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf);
 
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index f56925d..c2db770 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -972,7 +972,6 @@
             p_tcb->pending_ind_q = fixed_queue_new(SIZE_MAX);
             p_tcb->conf_timer = alarm_new("gatt.conf_timer");
             p_tcb->ind_ack_timer = alarm_new("gatt.ind_ack_timer");
-            p_tcb->sr_cmd.multi_rsp_q = fixed_queue_new(SIZE_MAX);
             p_tcb->in_use = TRUE;
             p_tcb->tcb_idx = i;
             p_tcb->transport = transport;
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index a042bb9..182b5ba 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -1070,14 +1070,18 @@
 **
 ** Parameters       gatt_if: applicaiton interface
 **                  bd_addr: peer device address.
-**                  is_direct: is a direct conenection or a background auto connection
+**                  is_direct: is a direct connection or a background auto connection
 **                  transport : Physical transport for GATT connection (BR/EDR or LE)
+**                  opportunistic: will not keep device connected if other apps
+**                      disconnect, will not update connected apps counter, when
+**                      disconnected won't cause physical disconnection.
 **
 ** Returns          TRUE if connection started; FALSE if connection start failure.
 **
 *******************************************************************************/
 extern BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr,
-                             BOOLEAN is_direct, tBT_TRANSPORT transport);
+                             BOOLEAN is_direct, tBT_TRANSPORT transport,
+                             BOOLEAN opportunistic);
 
 
 /*******************************************************************************
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index 44d87e7..a4d6cc2 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -281,6 +281,9 @@
 #define UUID_CODEC_MSBC                         0x0002   /* mSBC */
 #endif
 
+#define UUID_HF_IND_ENHANCED_DRIVER_SAFETY      0x0001   /* Assigned number for Enhanced Safety */
+#define UUID_HF_IND_BATTERY_LEVEL_STATUS        0x0002   /* Assigned number for Battery Status */
+
 /* Define all the 'Descriptor Type' values.
 */
 #define  NULL_DESC_TYPE                     0
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 62ef1db..87f526d 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -85,23 +85,23 @@
 #define SMP_MAX_FAIL_RSN_PER_SPEC   SMP_XTRANS_DERIVE_NOT_ALLOW
 
 /* self defined error code */
-#define SMP_PAIR_INTERNAL_ERR       (SMP_MAX_FAIL_RSN_PER_SPEC + 0x01) /* 0x0E */
+#define SMP_PAIR_INTERNAL_ERR       (SMP_MAX_FAIL_RSN_PER_SPEC + 0x01) /* 0x0F */
 
-/* 0x0F unknown IO capability, unable to decide association model */
-#define SMP_UNKNOWN_IO_CAP          (SMP_MAX_FAIL_RSN_PER_SPEC + 0x02) /* 0x0F */
+/* Unknown IO capability, unable to decide association model */
+#define SMP_UNKNOWN_IO_CAP          (SMP_MAX_FAIL_RSN_PER_SPEC + 0x02) /* 0x10 */
 
-#define SMP_INIT_FAIL               (SMP_MAX_FAIL_RSN_PER_SPEC + 0x03) /* 0x10 */
-#define SMP_CONFIRM_FAIL            (SMP_MAX_FAIL_RSN_PER_SPEC + 0x04) /* 0x11 */
-#define SMP_BUSY                    (SMP_MAX_FAIL_RSN_PER_SPEC + 0x05) /* 0x12 */
-#define SMP_ENC_FAIL                (SMP_MAX_FAIL_RSN_PER_SPEC + 0x06) /* 0x13 */
-#define SMP_STARTED                 (SMP_MAX_FAIL_RSN_PER_SPEC + 0x07) /* 0x14 */
-#define SMP_RSP_TIMEOUT             (SMP_MAX_FAIL_RSN_PER_SPEC + 0x08) /* 0x15 */
-#define SMP_DIV_NOT_AVAIL           (SMP_MAX_FAIL_RSN_PER_SPEC + 0x09) /* 0x16 */
+#define SMP_INIT_FAIL               (SMP_MAX_FAIL_RSN_PER_SPEC + 0x03) /* 0x11 */
+#define SMP_CONFIRM_FAIL            (SMP_MAX_FAIL_RSN_PER_SPEC + 0x04) /* 0x12 */
+#define SMP_BUSY                    (SMP_MAX_FAIL_RSN_PER_SPEC + 0x05) /* 0x13 */
+#define SMP_ENC_FAIL                (SMP_MAX_FAIL_RSN_PER_SPEC + 0x06) /* 0x14 */
+#define SMP_STARTED                 (SMP_MAX_FAIL_RSN_PER_SPEC + 0x07) /* 0x15 */
+#define SMP_RSP_TIMEOUT             (SMP_MAX_FAIL_RSN_PER_SPEC + 0x08) /* 0x16 */
+#define SMP_DIV_NOT_AVAIL           (SMP_MAX_FAIL_RSN_PER_SPEC + 0x09) /* 0x17 */
 
-/* 0x17 unspecified failed reason */
-#define SMP_FAIL                    (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0A) /* 0x17 */
+/* Unspecified failure reason */
+#define SMP_FAIL                    (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0A) /* 0x18 */
 
-#define SMP_CONN_TOUT               (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0B)
+#define SMP_CONN_TOUT               (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0B) /* 0x19 */
 #define SMP_SUCCESS                 0
 
 typedef UINT8 tSMP_STATUS;
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 7ebbef3..9104078 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -582,17 +582,16 @@
 ** Returns          void
 **
 *******************************************************************************/
-void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status)
+void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status,
+                  UINT16 interval, UINT16 latency, UINT16 timeout)
 {
-    tL2C_LCB *p_lcb;
-
-    L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt");
+    L2CAP_TRACE_DEBUG("%s", __func__);
 
     /* See if we have a link control block for the remote device */
-    p_lcb = l2cu_find_lcb_by_handle(handle);
+    tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
     if (!p_lcb)
     {
-        L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Invalid handle: %d", handle);
+        L2CAP_TRACE_WARNING("%s: Invalid handle: %d", __func__, handle);
         return;
     }
 
@@ -600,13 +599,14 @@
 
     if (status != HCI_SUCCESS)
     {
-        L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status);
+        L2CAP_TRACE_WARNING("%s: Error status: %d", __func__, status);
     }
 
     l2cble_start_conn_update(p_lcb);
 
-    L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask);
+    L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__, p_lcb->conn_update_mask);
 }
+
 /*******************************************************************************
 **
 ** Function         l2cble_process_sig_cmd
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 54e1f03..8af47d7 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -767,7 +767,8 @@
 extern BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb);
 extern void l2cble_notify_le_connection (BD_ADDR bda);
 extern void l2c_ble_link_adjust_allocation (void);
-extern void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status);
+extern void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status,
+                        UINT16 interval, UINT16 latency, UINT16 timeout);
 
 extern void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb);
 extern void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result);
diff --git a/stack/sdp/sdp_discovery.c b/stack/sdp/sdp_discovery.c
index ac43160..0beb04c 100644
--- a/stack/sdp/sdp_discovery.c
+++ b/stack/sdp/sdp_discovery.c
@@ -353,7 +353,7 @@
 #if (SDP_RAW_DATA_INCLUDED == TRUE)
 static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
 {
-    unsigned int    cpy_len;
+    unsigned int    cpy_len, rem_len;
     UINT32          list_len;
     UINT8           *p;
     UINT8           type;
@@ -380,10 +380,15 @@
             type = *p++;
             p = sdpu_get_len_from_type (p, type, &list_len);
         }
-        if(list_len && list_len < cpy_len )
+        if(list_len < cpy_len )
         {
             cpy_len = list_len;
         }
+        rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]);
+        if (cpy_len > rem_len) {
+            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);
@@ -568,6 +573,13 @@
     /* If p_reply is NULL, we were called for the initial read */
     if (p_reply)
     {
+        if (p_reply + 4 /* transaction ID and length */ + sizeof(lists_byte_count) >
+            p_reply_end) {
+            android_errorWriteLog(0x534e4554, "79884292");
+            sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
+            return;
+        }
+
 #if (SDP_DEBUG_RAW == TRUE)
         SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x",
             p_reply[0], p_reply[1], p_reply[2], p_reply[3]);
@@ -591,6 +603,13 @@
         SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d",
             p_ccb->list_len, lists_byte_count);
 #endif
+
+        if (p_reply + lists_byte_count + 1 /* continuation */ > p_reply_end) {
+            android_errorWriteLog(0x534e4554, "79884292");
+            sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
+            return;
+        }
+
         if (p_ccb->rsp_list == NULL)
             p_ccb->rsp_list = (UINT8 *)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
         memcpy (&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index ca98d86..100d35b 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -351,13 +351,16 @@
 
     /* Extract the record handle */
     BE_STREAM_TO_UINT32 (rec_handle, p_req);
+    param_len -= sizeof(rec_handle);
 
     /* Get the max list length we can send. Cap it at MTU size minus overhead */
     BE_STREAM_TO_UINT16 (max_list_len, p_req);
+    param_len -= sizeof(max_list_len);
 
     if (max_list_len > (p_ccb->rem_mtu_size - SDP_MAX_ATTR_RSPHDR_LEN))
         max_list_len = p_ccb->rem_mtu_size - SDP_MAX_ATTR_RSPHDR_LEN;
 
+    param_len = (UINT16)(p_req_end - p_req);
     p_req = sdpu_extract_attr_seq (p_req, param_len, &attr_seq);
 
     if ((!p_req) || (!attr_seq.num_attr) ||
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 78db66a..4c6cd59 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -26,6 +26,8 @@
 #include "stack/smp/smp_int.h"
 #include "utils/include/bt_utils.h"
 
+extern fixed_queue_t *btu_general_alarm_queue;
+
 #if SMP_INCLUDED == TRUE
 const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
 {
@@ -555,6 +557,9 @@
 {
     SMP_TRACE_DEBUG("%s", __func__);
     p_cb->status = *(UINT8 *)p_data;
+
+    /* Cancel pending auth complete timer if set */
+    alarm_cancel(p_cb->delayed_auth_timer_ent);
 }
 
 /*******************************************************************************
@@ -1300,7 +1305,6 @@
 *******************************************************************************/
 void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   reason = SMP_SUCCESS;
     SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
                       __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
 
@@ -1322,9 +1326,22 @@
             }
 
             if (p_cb->total_tx_unacked == 0)
-                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-            else
+            {
+                /*
+                 * Instead of declaring authorization complete immediately,
+                 * delay the event from being sent by SMP_DELAYED_AUTH_TIMEOUT_MS.
+                 * This allows the slave to send over Pairing Failed if the
+                 * last key is rejected.  During this waiting window, the
+                 * state should remain in SMP_STATE_BOND_PENDING.
+                 */
+                if (!alarm_is_scheduled(p_cb->delayed_auth_timer_ent)) {
+                    SMP_TRACE_DEBUG("%s delaying auth complete.", __func__);
+                    alarm_set_on_queue(p_cb->delayed_auth_timer_ent, SMP_DELAYED_AUTH_TIMEOUT_MS,
+                                       smp_delayed_auth_complete_timeout, NULL, btu_general_alarm_queue);
+                }
+            } else {
                 p_cb->wait_for_authorization_complete = TRUE;
+            }
         }
     }
 }
diff --git a/stack/smp/smp_api.c b/stack/smp/smp_api.c
index b3373b5..ddf9ba4 100644
--- a/stack/smp/smp_api.c
+++ b/stack/smp/smp_api.c
@@ -52,6 +52,7 @@
 {
     memset(&smp_cb, 0, sizeof(tSMP_CB));
     smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
+    smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
 
 #if defined(SMP_INITIAL_TRACE_LEVEL)
     smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index fbb4289..aea8538 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -51,6 +51,7 @@
 #endif
 
 #define SMP_WAIT_FOR_RSP_TIMEOUT_MS      (30 * 1000)
+#define SMP_DELAYED_AUTH_TIMEOUT_MS      500
 
 #define SMP_OPCODE_INIT                   0x04
 
@@ -340,7 +341,8 @@
     UINT16          total_tx_unacked;
     BOOLEAN         wait_for_authorization_complete;
     UINT8           cert_failure; /*failure case for certification */
-} tSMP_CB;
+    alarm_t         *delayed_auth_timer_ent;
+}tSMP_CB;
 
 /* Server Action functions are of this type */
 typedef void (*tSMP_ACT)(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
@@ -481,6 +483,7 @@
 extern void smp_convert_string_to_tk(BT_OCTET16 tk, UINT32 passkey);
 extern void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 * p_data);
 extern void smp_rsp_timeout(void *data);
+extern void smp_delayed_auth_complete_timeout(void *data);
 extern void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b);
 extern BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
                                  UINT8 *plain_text, UINT8 pt_len,
diff --git a/stack/smp/smp_l2c.c b/stack/smp/smp_l2c.c
index d401136..bd38525 100644
--- a/stack/smp/smp_l2c.c
+++ b/stack/smp/smp_l2c.c
@@ -29,7 +29,7 @@
 #include <string.h>
 #include "btm_ble_api.h"
 #include "l2c_api.h"
-
+#include "log/log.h"
 #include "smp_int.h"
 
 
@@ -264,6 +264,12 @@
                      (bd_addr[4]<<8)+bd_addr[5],
                      (connected) ? "connected" : "disconnected");
 
+    if (p_cb->role > HCI_ROLE_SLAVE) {
+        SMP_TRACE_ERROR ("%s: invalid role %d", __func__, p_cb->role);
+        android_errorWriteLog(0x534e4554, "80145946");
+        return;
+    }
+
     if (connected)
     {
         if(!p_cb->connect_initialized)
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index 38f9688..2727af8 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -241,7 +241,7 @@
 /* PAIR_RSP             */{ 0,    0,     0,      1,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
 /* CONFIRM              */{ 0,    0,     0,      0,     0,   1,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
 /* RAND                 */{ 0,    0,     0,      0,     0,   0,    1,   0,      0,      0,    1,    0,      0,     0,     0,    0,     0   },
-/* PAIR_FAIL            */{ 0,    0x81,  0,      0x81,  0x81,0x81, 0x81,0x81,   0x81,   0x81, 0x81, 0x81,   0x81,  0x81,  0,    0,     0   },
+/* PAIR_FAIL            */{ 0,    0x81,  0,      0x81,  0x81,0x81, 0x81,0x81,   0x81,   0x81, 0x81, 0x81,   0x81,  0x81,  0,    0x81,  0   },
 /* ENC_INFO             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    1,     0   },
 /* MASTER_ID            */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    4,     0   },
 /* ID_INFO              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    2,     0   },
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index f34fcbb..675cb42 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -374,6 +374,30 @@
 
 /*******************************************************************************
 **
+** Function         smp_delayed_auth_complete_timeout
+**
+** Description      Called when no pairing failed command received within timeout
+**                  period.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_delayed_auth_complete_timeout(UNUSED_ATTR void *data)
+{
+    /*
+     * Waited for potential pair failure. Send SMP_AUTH_CMPL_EVT if
+     * the state is still in bond pending.
+     */
+    if (smp_get_state() == SMP_STATE_BOND_PENDING)
+    {
+        UINT8 reason = SMP_SUCCESS;
+        SMP_TRACE_EVENT("%s sending delayed auth complete.", __func__);
+        smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         smp_build_pairing_req_cmd
 **
 ** Description      Build pairing request command.
@@ -841,10 +865,12 @@
     SMP_TRACE_EVENT("smp_cb_cleanup");
 
     alarm_free(p_cb->smp_rsp_timer_ent);
+    alarm_free(p_cb->delayed_auth_timer_ent);
     memset(p_cb, 0, sizeof(tSMP_CB));
     p_cb->p_callback = p_callback;
     p_cb->trace_level = trace_level;
     p_cb->smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
+    p_cb->delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
 }
 
 /*******************************************************************************
diff --git a/stack/srvc/srvc_dis.c b/stack/srvc/srvc_dis.c
index c17c660..12ae5a5 100644
--- a/stack/srvc/srvc_dis.c
+++ b/stack/srvc/srvc_dis.c
@@ -472,7 +472,7 @@
 
     if (conn_id == GATT_INVALID_CONN_ID)
     {
-        return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE, BT_TRANSPORT_LE);
+        return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE, BT_TRANSPORT_LE, false);
     }
 
     return dis_gatt_c_read_dis_req(conn_id);
diff --git a/vendor_libs/linux/bt_vendor_linux.c b/vendor_libs/linux/bt_vendor_linux.c
index eec3e01..41abc8a 100644
--- a/vendor_libs/linux/bt_vendor_linux.c
+++ b/vendor_libs/linux/bt_vendor_linux.c
@@ -202,10 +202,10 @@
     }
 
     if (fds[0].revents & POLLIN) {
-      n = read(fd, &ev, sizeof(struct mgmt_pkt));
+      OSI_NO_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt)));
       if (n < 0) {
-        LOG_ERROR(LOG_TAG,
-                  "Error reading control channel");
+        LOG_ERROR(LOG_TAG, "Error reading control channel: %s",
+                  strerror(errno));
         ret = -1;
         break;
       }