am 556cc857: Merge "Remove unused LOCAL_LDLIBS."

* commit '556cc857c33ed1043e6c8a1f9235ac3eab058251':
  Remove unused LOCAL_LDLIBS.
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 1137349..f778716 100755
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -674,6 +674,11 @@
     int i;
     tBTA_DM_SEC sec_event;
 
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+    /* need to remove all pending background connection before unpair */
+    BTA_GATTC_CancelOpen(0, p_dev->bd_addr, FALSE);
+#endif
+
     if (BTM_IsAclConnectionUp(p_dev->bd_addr))
     {
         /* Take the link down first, and mark the device for removal when disconnected */
@@ -693,6 +698,11 @@
     else    /* Ok to remove the device in application layer */
     {
         BTM_SecDeleteDevice(p_dev->bd_addr);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+        /* remove all cached GATT information */
+        BTA_GATTC_Refresh(p_dev->bd_addr);
+#endif
+
         if( bta_dm_cb.p_sec_cback )
         {
             bdcpy(sec_event.link_down.bd_addr, p_dev->bd_addr);
@@ -3460,6 +3470,10 @@
             if( bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING )
             {
                 BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+                /* remove all cached GATT information */
+                BTA_GATTC_Refresh(p_bda);
+#endif
                 issue_unpair_cb = TRUE;
             }
 
@@ -3769,6 +3783,12 @@
     else
     {
         BTM_SecDeleteDevice (remote_bd_addr);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+        /* need to remove all pending background connection */
+        BTA_GATTC_CancelOpen(0, remote_bd_addr, FALSE);
+        /* remove all cached GATT information */
+        BTA_GATTC_Refresh(remote_bd_addr);
+#endif
     }
 }
 
@@ -4998,6 +5018,7 @@
                         p_data->ble_set_adv_params.p_dir_bda,
                         BTA_DM_BLE_ADV_CHNL_MAP);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_dm_ble_set_adv_config
@@ -5013,6 +5034,34 @@
                         (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
 }
 
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_scan_rsp
+**
+** Description      This function set the customized ADV scan resp. configuration
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data)
+{
+    BTM_BleWriteScanRsp(p_data->ble_set_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_broadcast
+**
+** Description      Starts or stops LE broadcasts
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data)
+{
+    BTM_BleBroadcast(p_data->ble_observe.start);
+}
 
 #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
 #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 941213a..e37548e 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -1510,6 +1510,60 @@
         bta_sys_sendmsg(p_msg);
     }
 }
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetScanRsp
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg)
+{
+    tBTA_DM_API_SET_ADV_CONFIG  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_SET_SCAN_RSP_EVT;
+		p_msg->data_mask = data_mask;
+        p_msg->p_adv_cfg = p_adv_cfg;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleBroadcast
+**
+** Description      This function starts or stops LE broadcasting.
+**
+** Parameters       start: start or stop broadcast.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleBroadcast (BOOLEAN start)
+{
+    tBTA_DM_API_BLE_OBSERVE   *p_msg;
+
+    APPL_TRACE_API1("BTA_DmBleBroadcast: start = %d ", start);
+
+    if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_BROADCAST_EVT;
+        p_msg->start = start;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
 #endif
 /*******************************************************************************
 **
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index d87dbf3..dd3e16c 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -101,6 +101,8 @@
     BTA_DM_API_BLE_OBSERVE_EVT,
     BTA_DM_API_BLE_ADV_PARAM_EVT,
     BTA_DM_API_BLE_SET_ADV_CONFIG_EVT,
+    BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
+    BTA_DM_API_BLE_BROADCAST_EVT,
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -996,6 +998,8 @@
 extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
 
 #endif
 extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index 50f871f..0f6b91a 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -98,6 +98,8 @@
     bta_dm_ble_observe,
     bta_dm_ble_set_adv_params,     /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
     bta_dm_ble_set_adv_config,     /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */
+    bta_dm_ble_set_scan_rsp,       /* BTA_DM_API_BLE_SET_SCAN_RSP_EVT */
+    bta_dm_ble_broadcast,          /* BTA_DM_API_BLE_BROADCAST_EVT */
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index f5b60fa..7563ec3 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -52,13 +52,16 @@
 
 static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg);
 
+static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda);
+
 static tGATT_CBACK bta_gattc_cl_cback =
 {
     bta_gattc_conn_cback,
     bta_gattc_cmpl_cback,
     bta_gattc_disc_res_cback,
     bta_gattc_disc_cmpl_cback,
-    NULL
+    NULL,
+    bta_gattc_enc_cmpl_cback
 };
 
 /* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
@@ -399,6 +402,34 @@
 
     }
 }
+
+/*******************************************************************************
+**
+** Function         bta_gattc_process_enc_cmpl
+**
+** Description      process encryption complete message.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC_RCB *p_clreg;
+    tBTA_GATTC cb_data;
+
+    p_clreg = bta_gattc_cl_get_regcb(p_msg->enc_cmpl.client_if);
+
+    if (p_clreg && p_clreg->p_cback)
+    {
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+        cb_data.enc_cmpl.client_if = p_msg->enc_cmpl.client_if;
+        bdcpy(cb_data.enc_cmpl.remote_bda, p_msg->enc_cmpl.remote_bda);
+
+        (*p_clreg->p_cback)(BTA_GATTC_ENC_CMPL_CB_EVT, &cb_data);
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         bta_gattc_cancel_open_error
@@ -1635,6 +1666,50 @@
 
 /*******************************************************************************
 **
+** Function         bta_gattc_enc_cmpl_cback
+**
+** Description      encryption complete callback function to GATT client stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda)
+{
+    tBTA_GATTC_DATA *p_buf;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+
+    if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
+    {
+        return;
+    }
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    /* filter this event just for BTA HH LE GATT client,
+       In the future, if we want to enable encryption complete event
+       for all GATT clients, we can remove this code */
+    if (!bta_hh_le_is_hh_gatt_if(gattc_if))
+    {
+        return;
+    }
+#endif
+
+    APPL_TRACE_DEBUG1("bta_gattc_enc_cmpl_cback: cif = %d", gattc_if);
+
+    if ((p_buf = (tBTA_GATTC_DATA *) GKI_getbuf(sizeof(tBTA_GATTC_DATA))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
+
+        p_buf->enc_cmpl.hdr.event            = BTA_GATTC_ENC_CMPL_EVT;
+        p_buf->enc_cmpl.hdr.layer_specific   = p_clcb->bta_conn_id;
+        p_buf->enc_cmpl.client_if            = gattc_if;
+        bdcpy(p_buf->enc_cmpl.remote_bda, bda);
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         bta_gattc_process_api_refresh
 **
 ** Description      process refresh API to delete cache and start a new discovery
@@ -2053,5 +2128,27 @@
         }
     }
 }
+
+/*******************************************************************************
+**
+** Function         bta_gattc_broadcast
+**
+** Description      Start or stop broadcasting
+**
+** Returns          void
+**
+********************************************************************************/
+void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    tBTA_GATTC_RCB      *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if);
+    tBTA_GATTC          cb_data;
+    (void)(p_cb);
+
+    cb_data.reg_oper.client_if = p_msg->api_listen.client_if;
+    cb_data.reg_oper.status = BTM_BleBroadcast(p_msg->api_listen.start);
+
+    if (p_clreg && p_clreg->p_cback)
+        (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data);
+}
 #endif
 #endif
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
index fff1a55..d264458 100644
--- a/bta/gatt/bta_gattc_api.c
+++ b/bta/gatt/bta_gattc_api.c
@@ -1056,5 +1056,31 @@
     return;
 }
 
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Broadcast
+**
+** Description      Start broadcasting (non-connectable advertisements)
+**
+** Parameters       client_if: client interface.
+**                  start: to start or stop listening for connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start)
+{
+    tBTA_GATTC_API_LISTEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_LISTEN *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_BROADCAST_EVT;
+        p_buf->client_if = client_if;
+        p_buf->start = start;
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
 #endif /* BTA_GATT_INCLUDED */
 
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index c2056d4..255090d 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -69,7 +69,9 @@
     BTA_GATTC_API_REG_EVT,
     BTA_GATTC_API_DEREG_EVT,
     BTA_GATTC_API_LISTEN_EVT,
-    BTA_GATTC_API_DISABLE_EVT
+    BTA_GATTC_API_BROADCAST_EVT,
+    BTA_GATTC_API_DISABLE_EVT,
+    BTA_GATTC_ENC_CMPL_EVT
 };
 typedef UINT16 tBTA_GATTC_INT_EVT;
 
@@ -195,6 +197,13 @@
     tGATT_DISCONN_REASON    reason;
 }tBTA_GATTC_INT_CONN;
 
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_IF           client_if;
+}tBTA_GATTC_ENC_CMPL;
+
 typedef union
 {
     BT_HDR                      hdr;
@@ -213,6 +222,7 @@
     tBTA_GATTC_CI_EVT           ci_save;
     tBTA_GATTC_CI_LOAD          ci_load;
     tBTA_GATTC_INT_CONN         int_conn;
+    tBTA_GATTC_ENC_CMPL         enc_cmpl;
 
     tBTA_GATTC_INT_START_IF     int_start_if;
     tBTA_GATTC_INT_DEREG        int_dereg;
@@ -433,6 +443,7 @@
 extern void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
 extern void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
 extern void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB  *p_clreg);
+extern void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
 
 /* function within state machine */
 extern void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
@@ -474,6 +485,7 @@
 extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
 #if BLE_INCLUDED == TRUE
 extern void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
 #endif
 /* utility functions */
 extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda);
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
index 9427f89..638f2f9 100644
--- a/bta/gatt/bta_gattc_main.c
+++ b/bta/gatt/bta_gattc_main.c
@@ -385,7 +385,15 @@
         case BTA_GATTC_API_LISTEN_EVT:
             bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg);
             break;
+        case BTA_GATTC_API_BROADCAST_EVT:
+            bta_gattc_broadcast(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
 #endif
+
+        case BTA_GATTC_ENC_CMPL_EVT:
+            bta_gattc_process_enc_cmpl(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
         default:
             if (p_msg->event == BTA_GATTC_INT_CONN_EVT)
                 p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA *) p_msg);
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index f59b593..f1bd88e 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -49,7 +49,8 @@
     NULL,
     NULL,
     NULL,
-    bta_gatts_send_request_cback
+    bta_gatts_send_request_cback,
+    NULL
 };
 
 tGATT_APPL_INFO bta_gatts_nv_cback =
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index 99a8b82..1ac40da 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -67,6 +67,7 @@
     BTA_HH_GATT_READ_DESCR_CMPL_EVT,
     BTA_HH_GATT_WRITE_DESCR_CMPL_EVT,
     BTA_HH_API_SCPP_UPDATE_EVT,
+    BTA_HH_GATT_ENC_CMPL_EVT,
 #endif
 
     /* not handled by execute state machine */
@@ -182,6 +183,7 @@
     tBTA_HH_LE_CLOSE         le_close;
     tBTA_GATTC_OPEN          le_open;
     tBTA_HH_SCPP_UPDATE      le_scpp_update;
+    tBTA_GATTC_ENC_CMPL_CB   le_enc_cmpl;
 #endif
 } tBTA_HH_DATA;
 
@@ -201,7 +203,7 @@
 }tBTA_HH_LE_RPT;
 
 #ifndef BTA_HH_LE_RPT_MAX
-#define BTA_HH_LE_RPT_MAX       10
+#define BTA_HH_LE_RPT_MAX       20
 #endif
 
 typedef struct
@@ -283,6 +285,7 @@
     UINT8               scps_notify;   /* scan refresh supported/notification enabled */
 #endif
 
+    BOOLEAN             security_pending;
 } tBTA_HH_DEV_CB;
 
 /* key board parsing control block */
@@ -404,7 +407,7 @@
 extern void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
 extern void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
 extern void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
-
+extern void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
 
 #if BTA_HH_DEBUG
 extern void bta_hh_trace_dev_db(void);
diff --git a/bta/hh/bta_hh_le.c b/bta/hh/bta_hh_le.c
index 52de4d6..dbbfb32 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -28,6 +28,7 @@
 #include "bta_hh_co.h"
 #include "bta_gatt_api.h"
 #include "srvc_api.h"
+#include "btm_int.h"
 
 #ifndef BTA_HH_LE_RECONN
 #define BTA_HH_LE_RECONN    TRUE
@@ -37,7 +38,7 @@
 
 #define BTA_HH_LE_RPT_TYPE_VALID(x)     ((x) <= BTA_LE_HID_RPT_FEATURE && (x)>=BTA_LE_HID_RPT_INPUT)
 
-#define BTA_HH_LE_RPT_INST_ID_MAP(s,c)  (UINT8)(((s)<<4)||(c))
+#define BTA_HH_LE_RPT_INST_ID_MAP(s,c)  (UINT8)(((s)<<4)|(c))
 #define BTA_HH_LE_RPT_GET_SRVC_INST_ID(x)  (UINT8)(x  >> 4)
 #define BTA_HH_LE_RPT_GET_RPT_INST_ID(x)  (UINT8)(x & 0x0f)
 
@@ -638,6 +639,8 @@
 
     while (p_rpt != NULL)
     {
+        if (!p_rpt->in_use) break;
+
         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
         {
             /* is battery report */
@@ -718,9 +721,10 @@
 #endif
     }
 
-    if (p_rpt->index < BTA_HH_LE_RPT_MAX)
+    if (p_rpt->index < BTA_HH_LE_RPT_MAX - 1)
         p_rpt ++;
-
+    else
+        p_rpt = NULL;
     /* read next report reference descriptor  */
     bta_hh_le_read_rpt_ref_descr(p_dev_cb, p_rpt);
 
@@ -1084,7 +1088,7 @@
                                           p_char_id->char_id.inst_id,
                                           prop) == NULL)
         {
-            APPL_TRACE_ERROR0("Add report entry failed !!!")
+            APPL_TRACE_ERROR0("Add report entry failed !!!");
             break;
         }
 
@@ -1125,7 +1129,7 @@
                                       prop) == NULL)
 
     {
-        APPL_TRACE_ERROR0("Add report entry failed !!!")
+        APPL_TRACE_ERROR0("Add report entry failed !!!");
     }
 
     return;
@@ -1257,6 +1261,28 @@
         bta_hh_le_api_disc_act(p_cb);
 
 }
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_notify_enc_cmpl
+**
+** Description      process GATT encryption complete event
+**
+** Returns
+**
+*******************************************************************************/
+void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
+{
+    if (p_cb == NULL || p_cb->security_pending == FALSE ||
+        p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
+    {
+        return;
+    }
+
+    p_cb->security_pending = FALSE;
+    bta_hh_start_security(p_cb, NULL);
+}
+
 /*******************************************************************************
 **
 ** Function         bta_hh_start_security
@@ -1269,6 +1295,19 @@
 void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
 {
     UINT8           sec_flag=0;
+    tBTM_SEC_DEV_REC  *p_dev_rec;
+
+    p_dev_rec = btm_find_dev(p_cb->addr);
+    if (p_dev_rec)
+    {
+        if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+            p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
+        {
+            /* if security collision happened, wait for encryption done */
+            p_cb->security_pending = TRUE;
+            return;
+        }
+    }
 
     /* verify bond */
     BTM_GetSecurityFlags(p_cb->addr, &sec_flag);
@@ -1372,7 +1411,7 @@
         p_buf->reason               = p_data->reason;
 
         p_dev_cb->conn_id           = BTA_GATT_INVALID_CONN_ID;
-
+        p_dev_cb->security_pending  = FALSE;
         bta_sys_sendmsg(p_buf);
     }
 }
@@ -2593,6 +2632,8 @@
 *******************************************************************************/
 UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
 {
+    p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+    bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
 
     /* update DI information */
     bta_hh_update_di_info(p_cb,
@@ -2709,7 +2750,9 @@
 
         case BTA_GATTC_OPEN_EVT: /* 2 */
             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
-            bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
+            if (p_dev_cb) {
+                bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
+            }
             break;
 
         case BTA_GATTC_READ_CHAR_EVT: /* 3 */
@@ -2751,6 +2794,15 @@
         case BTA_GATTC_NOTIF_EVT: /* 10 */
             bta_hh_le_input_rpt_notify(&p_data->notify);
             break;
+
+        case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
+            p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
+            if (p_dev_cb) {
+                bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
+                              (tBTA_HH_DATA *)&p_data->enc_cmpl);
+            }
+            break;
+
         default:
             break;
     }
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
index bf54e57..c2554c1 100644
--- a/bta/hh/bta_hh_main.c
+++ b/bta/hh/bta_hh_main.c
@@ -66,7 +66,7 @@
     BTA_HH_START_SEC,
     BTA_HH_SEC_CMPL,
     BTA_HH_LE_UPDATE_SCPP,
-
+    BTA_HH_GATT_ENC_CMPL,
 #endif
     BTA_HH_NUM_ACTIONS
 };
@@ -106,6 +106,7 @@
     ,bta_hh_start_security
     ,bta_hh_security_cmpl
     ,bta_hh_le_update_scpp
+    ,bta_hh_le_notify_enc_cmpl
 #endif
 };
 
@@ -140,6 +141,7 @@
 /* READ_DESCR_CMPL_EVT */        ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST  }
 /* WRITE_DESCR_CMPL_EVT */       ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST   }
 /* SCPP_UPDATE_EVT */            ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST   }
 #endif
 
 };
@@ -170,6 +172,7 @@
 /* READ_DESCR_CMPL_EVT */        ,{BTA_HH_W4_LE_READ_DESCR, BTA_HH_W4_CONN_ST  }
 /* WRITE_DESCR_CMPL_EVT */       ,{BTA_HH_WRITE_DESCR,   BTA_HH_W4_CONN_ST   }
 /* SCPP_UPDATE_EVT */            ,{BTA_HH_IGNORE,           BTA_HH_W4_CONN_ST   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST }
 #endif
 };
 
@@ -199,6 +202,7 @@
 /* READ_DESCR_CMPL_EVT */        ,{BTA_HH_LE_READ_DESCR, BTA_HH_CONN_ST     }   /* do not currently read any descr when connection up */
 /* WRITE_DESCR_CMPL_EVT */       ,{BTA_HH_WRITE_DESCR,   BTA_HH_CONN_ST     }   /* do not currently write any descr when connection up */
 /* SCPP_UPDATE_EVT */            ,{BTA_HH_LE_UPDATE_SCPP,  BTA_HH_CONN_ST   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_IGNORE,        BTA_HH_CONN_ST     }
 #endif
 };
 #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
@@ -226,6 +230,7 @@
 /* READ_DESCR_CMPL_EVT */         {BTA_HH_IGNORE,        BTA_HH_W4_SEC   },
 /* WRITE_DESCR_CMPL_EVT */        {BTA_HH_IGNORE,        BTA_HH_W4_SEC   }
 /* SCPP_UPDATE_EVT */            ,{BTA_HH_IGNORE,        BTA_HH_W4_SEC   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_GATT_ENC_CMPL, BTA_HH_W4_SEC   }
 };
 #endif
 
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index e52e699..4345fbf 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -1884,7 +1884,7 @@
 *******************************************************************************/
 BTA_API extern void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable);
 
-#if BLE_INCLUDE == TRUE
+#if BLE_INCLUDED == TRUE
 // btla-specific --
 /*******************************************************************************
 **
@@ -1927,6 +1927,34 @@
 *******************************************************************************/
 BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
                                            tBTA_BLE_ADV_DATA *p_adv_cfg);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetScanRsp
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask,
+                                         tBTA_BLE_ADV_DATA *p_adv_cfg);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleBroadcast
+**
+** Description      This function starts or stops LE broadcasting.
+**
+** Parameters       start: start or stop broadcast.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleBroadcast (BOOLEAN start);
+
 #endif
 
 #ifdef __cplusplus
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 93eadd5..7c974c5 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -115,6 +115,7 @@
 #define BTA_GATTC_CANCEL_OPEN_EVT   14  /* cancel open event */
 #define BTA_GATTC_SRVC_CHG_EVT      15  /* service change event */
 #define BTA_GATTC_LISTEN_EVT        16  /* listen event */
+#define BTA_GATTC_ENC_CMPL_CB_EVT   17  /* encryption complete callback event */
 
 typedef UINT8 tBTA_GATTC_EVT;
 
@@ -349,6 +350,12 @@
 }tBTA_GATTC_OPEN_CLOSE;
 // btla-specific --
 
+typedef struct
+{
+    tBTA_GATTC_IF       client_if;
+    BD_ADDR             remote_bda;
+}tBTA_GATTC_ENC_CMPL_CB;
+
 typedef union
 {
     tBTA_GATT_STATUS        status;
@@ -362,6 +369,7 @@
     tBTA_GATTC_WRITE        write;            /* write complete data */
     tBTA_GATTC_EXEC_CMPL    exec_cmpl;       /*  execute complete */
     tBTA_GATTC_NOTIFY       notify;           /* notification/indication event data */
+    tBTA_GATTC_ENC_CMPL_CB  enc_cmpl;
     BD_ADDR                 remote_bda;     /* service change event */
 } tBTA_GATTC;
 
@@ -1023,6 +1031,21 @@
 BTA_API extern void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda);
 
 /*******************************************************************************
+**
+** Function         BTA_GATTC_Broadcast
+**
+** Description      Start broadcasting (non-connectable advertisements)
+**
+** Parameters       client_if: client interface.
+**                  start: to start or stop listening for connection
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start);
+
+
+/*******************************************************************************
 **  BTA GATT Server API
 ********************************************************************************/
 
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 41507fb..951b376 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -30,6 +30,7 @@
 #define BTIF_STORAGE_FILL_PROPERTY(p_prop, t, l, p_v) \
          (p_prop)->type = t;(p_prop)->len = l; (p_prop)->val = (p_v);
 
+#define  BTIF_STORAGE_MAX_ALLOWED_REMOTE_DEVICE 512
 
 /*******************************************************************************
 **  Functions
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
index 476aaba..aa42dbc 100755
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -155,7 +155,6 @@
         return;
 
     btif_shutdown_bluetooth();
-    bt_utils_cleanup();
 
     /* hal callbacks reset upon shutdown complete callback */
 
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
index 40f19d0..9504c3c 100644
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -37,6 +37,7 @@
 
 #define LOG_TAG "BTIF_CORE"
 #include "btif_api.h"
+#include "bt_utils.h"
 #include "bta_api.h"
 #include "gki.h"
 #include "btu.h"
@@ -737,6 +738,14 @@
 {
     BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
 
+    if (btif_core_state == BTIF_CORE_STATE_DISABLING)
+    {
+        BTIF_TRACE_WARNING0("shutdown during disabling");
+        /* shutdown called before disabling is done */
+        btif_shutdown_pending = 1;
+        return BT_STATUS_NOT_READY;
+    }
+
     if (btif_is_enabled())
     {
         BTIF_TRACE_WARNING0("shutdown while still enabled, initiate disable");
@@ -765,6 +774,8 @@
 
     btif_dut_mode = 0;
 
+    bt_utils_cleanup();
+
     BTIF_TRACE_DEBUG1("%s done", __FUNCTION__);
 
     return BT_STATUS_SUCCESS;
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index ce51ce2..6aab986 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -104,8 +104,8 @@
 
 typedef struct
 {
-    tBTM_BLE_AD_MASK mask;
-    tBTM_BLE_ADV_DATA data;
+    tBTA_BLE_AD_MASK mask;
+    tBTA_BLE_ADV_DATA data;
 } btgatt_adv_data;
 
 typedef struct
@@ -463,10 +463,31 @@
         case BTIF_GATT_OBSERVE_EVT:
         {
             btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
-            if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address))
+            uint8_t remote_name_len;
+            uint8_t *p_eir_remote_name=NULL;
+
+            p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
+                                         BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+
+            if(p_eir_remote_name == NULL)
             {
-                btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type);
-                btif_gattc_update_properties(p_btif_cb);
+                p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
+                                BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
+            }
+
+            if ((p_btif_cb->addr_type != BLE_ADDR_RANDOM) || (p_eir_remote_name))
+            {
+               if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address))
+               {
+                  static const char* exclude_filter[] =
+                        {"LinkKey", "LE_KEY_PENC", "LE_KEY_PID", "LE_KEY_PCSRK", "LE_KEY_LENC", "LE_KEY_LCSRK"};
+
+                  btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type);
+                  btif_gattc_update_properties(p_btif_cb);
+                  btif_config_filter_remove("Remote", exclude_filter, sizeof(exclude_filter)/sizeof(char*),
+                  BTIF_STORAGE_MAX_ALLOWED_REMOTE_DEVICE);
+               }
+
             }
             HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb,
                       &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value);
@@ -819,17 +840,46 @@
             break;
 
         case BTIF_GATTC_LISTEN:
+#ifdef BLE_PERIPHERAL_MODE_SUPPORT
             BTA_GATTC_Listen(p_cb->client_if, p_cb->start, NULL);
+#else
+            BTA_GATTC_Broadcast(p_cb->client_if, p_cb->start);
+#endif
             break;
 
         case BTIF_GATTC_SET_ADV_DATA:
         {
             if (p_cb->start == 0)
-                BTM_BleWriteAdvData(p_cb->adv_data.mask, &p_cb->adv_data.data);
+                BTA_DmBleSetAdvConfig(p_cb->adv_data.mask, &p_cb->adv_data.data);
             else
-                BTM_BleWriteScanRsp(p_cb->adv_data.mask, &p_cb->adv_data.data);
+                BTA_DmBleSetScanRsp(p_cb->adv_data.mask, &p_cb->adv_data.data);
+
+            // Cleanup ...
+
+            // ... manufacturer data
             if (p_cb->adv_data.data.manu.p_val != NULL)
                 GKI_freebuf(p_cb->adv_data.data.manu.p_val);
+
+            // ... service data
+            if (p_cb->adv_data.data.p_proprietary != NULL)
+            {
+                int i = 0;
+                tBTA_BLE_PROP_ELEM *p_elem = p_cb->adv_data.data.p_proprietary->p_elem;
+                while (i++ != p_cb->adv_data.data.p_proprietary->num_elem && p_elem)
+                {
+                    if (p_elem->p_val != NULL)
+                        GKI_freebuf(p_elem->p_val);
+                    ++p_elem;
+                }
+                if (p_cb->adv_data.data.p_proprietary->p_elem != NULL)
+                    GKI_freebuf(p_cb->adv_data.data.p_proprietary->p_elem);
+                GKI_freebuf(p_cb->adv_data.data.p_proprietary);
+            }
+
+            // ... service list
+            if (p_cb->adv_data.data.services.p_uuid != NULL)
+                GKI_freebuf(p_cb->adv_data.data.services.p_uuid);
+
             break;
         }
 
@@ -904,7 +954,9 @@
 
 static bt_status_t btif_gattc_set_adv_data(int client_if, bool set_scan_rsp, bool include_name,
                 bool include_txpower, int min_interval, int max_interval, int appearance,
-                uint16_t manufacturer_len, char* manufacturer_data)
+                uint16_t manufacturer_len, char* manufacturer_data,
+                uint16_t service_data_len, char* service_data,
+                uint16_t service_uuid_len, char* service_uuid)
 {
     CHECK_BTGATT_INIT();
     btif_gattc_cb_t btif_cb;
@@ -950,6 +1002,112 @@
         }
     }
 
+    tBTA_BLE_PROP_ELEM *p_elem_service_data = NULL;
+    tBTA_BLE_PROP_ELEM *p_elem_service_128 = NULL;
+
+    if (service_data_len > 0 && service_data != NULL)
+    {
+        p_elem_service_data = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
+        if (p_elem_service_data != NULL)
+        {
+            p_elem_service_data->p_val = GKI_getbuf(service_data_len);
+            if (p_elem_service_data->p_val != NULL)
+            {
+                p_elem_service_data->adv_type = BTM_BLE_AD_TYPE_SERVICE_DATA;
+                p_elem_service_data->len = service_data_len;
+                memcpy(p_elem_service_data->p_val, service_data, service_data_len);
+
+            } else {
+                GKI_freebuf(p_elem_service_data);
+                p_elem_service_data = NULL;
+            }
+        }
+    }
+
+    if (service_uuid_len > 0 && service_uuid != NULL)
+    {
+        btif_cb.adv_data.data.services.list_cmpl = FALSE;
+        btif_cb.adv_data.data.services.num_service = 0;
+
+        btif_cb.adv_data.data.services.p_uuid =
+            GKI_getbuf(service_uuid_len / LEN_UUID_128 * LEN_UUID_16);
+        if (btif_cb.adv_data.data.services.p_uuid != NULL)
+        {
+            UINT16 *p_uuid_out = btif_cb.adv_data.data.services.p_uuid;
+            while (service_uuid_len >= LEN_UUID_128)
+            {
+                bt_uuid_t uuid;
+                memset(&uuid, 0, sizeof(bt_uuid_t));
+                memcpy(&uuid.uu, service_uuid, LEN_UUID_128);
+
+                tBT_UUID bt_uuid;
+                memset(&bt_uuid, 0, sizeof(tBT_UUID));
+                btif_to_bta_uuid(&bt_uuid, &uuid);
+
+                if (bt_uuid.len == LEN_UUID_16)
+                {
+                    btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_SERVICE;
+                    ++btif_cb.adv_data.data.services.num_service;
+                    *p_uuid_out++ = bt_uuid.uu.uuid16;
+
+                } else if (bt_uuid.len == LEN_UUID_128 && p_elem_service_128 == NULL) {
+                    /* Currently, only one 128-bit UUID is supported */
+                    p_elem_service_128 = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
+                    if (p_elem_service_128 != NULL)
+                    {
+                        p_elem_service_128->p_val = GKI_getbuf(LEN_UUID_128);
+                        if (p_elem_service_128->p_val != NULL)
+                        {
+                            p_elem_service_128->adv_type = BTM_BLE_AD_TYPE_128SRV_PART;
+                            p_elem_service_128->len = LEN_UUID_128;
+                            memcpy(p_elem_service_128->p_val, bt_uuid.uu.uuid128, LEN_UUID_128);
+
+                        } else {
+                            GKI_freebuf(p_elem_service_128);
+                            p_elem_service_128 = NULL;
+                        }
+                    }
+                }
+
+                service_uuid += LEN_UUID_128;
+                service_uuid_len -= LEN_UUID_128;
+            }
+        }
+    }
+
+    if (p_elem_service_data != NULL || p_elem_service_128 != NULL)
+    {
+        btif_cb.adv_data.data.p_proprietary = GKI_getbuf(sizeof(tBTA_BLE_PROPRIETARY));
+        if (btif_cb.adv_data.data.p_proprietary != NULL)
+        {
+            tBTA_BLE_PROPRIETARY *p_prop = btif_cb.adv_data.data.p_proprietary;
+            tBTA_BLE_PROP_ELEM *p_elem = NULL;
+            p_prop->num_elem = 0;
+            btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_PROPRIETARY;
+
+            if (p_elem_service_128 != NULL)
+                ++p_prop->num_elem;
+
+            if (p_elem_service_data != NULL)
+                ++p_prop->num_elem;
+
+            p_prop->p_elem = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM) * p_prop->num_elem);
+            p_elem = p_prop->p_elem;
+
+            if (p_elem_service_128 != NULL)
+            {
+                memcpy(p_elem++, p_elem_service_128, sizeof(tBTA_BLE_PROP_ELEM));
+                GKI_freebuf(p_elem_service_128);
+            }
+
+            if (p_elem_service_data != NULL)
+            {
+                memcpy(p_elem++, p_elem_service_data, sizeof(tBTA_BLE_PROP_ELEM));
+                GKI_freebuf(p_elem_service_data);
+            }
+        }
+    }
+
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
                                  (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
 }
diff --git a/btif/src/btif_gatt_test.c b/btif/src/btif_gatt_test.c
index 8c23d56..2a316fe 100644
--- a/btif/src/btif_gatt_test.c
+++ b/btif/src/btif_gatt_test.c
@@ -197,6 +197,7 @@
     btif_test_command_complete_cback,
     btif_test_discovery_result_cback,
     btif_test_discovery_complete_cback,
+    NULL,
     NULL
 };
 
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 1c64e3e..8eeddfc 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -533,6 +533,9 @@
         return;
     }
 
+    /* need to notify up-layer device is disconnected to avoid state out of sync with up-layer */
+    HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr), BTHH_CONN_STATE_DISCONNECTED);
+
     p_dev->dev_status = BTHH_CONN_STATE_UNKNOWN;
     p_dev->dev_handle = BTA_HH_INVALID_HANDLE;
     if (btif_hh_cb.device_num > 0) {
@@ -935,9 +938,18 @@
             }
             {
                 char *cached_name = NULL;
-                char name[] = "Broadcom Bluetooth HID";
-                if (cached_name == NULL) {
-                    cached_name = name;
+                bt_bdname_t bdname;
+                bt_property_t prop_name;
+                BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
+                                           sizeof(bt_bdname_t), &bdname);
+                if (btif_storage_get_remote_device_property(
+                    &p_dev->bd_addr, &prop_name) == BT_STATUS_SUCCESS)
+                {
+                    cached_name = (char *)bdname.name;
+                }
+                else
+                {
+                    cached_name = "Bluetooth HID";
                 }
 
                 BTIF_TRACE_WARNING2("%s: name = %s", __FUNCTION__, cached_name);
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index f566df4..65cffbc 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -38,7 +38,7 @@
 #define LOG_TAG "BTIF_STORAGE"
 
 #include "btif_api.h"
-
+#include "btif_storage.h"
 #include "btif_util.h"
 #include "bd.h"
 #include "gki.h"
@@ -150,7 +150,6 @@
 #define BTIF_STORAGE_HL_APP_DATA     "hl_app_data_"
 #define BTIF_STORAGE_HL_APP_MDL_DATA "hl_app_mdl_data_"
 
-#define  BTIF_STORAGE_MAX_ALLOWED_REMOTE_DEVICE 512
 /************************************************************************************
 **  Local type definitions
 ************************************************************************************/
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 6f2f454..f25bfd5 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -1591,7 +1591,28 @@
         role = HCI_ROLE_UNKNOWN;
 
         if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+        {
             btm_ble_dir_adv_tout();
+        }
+        /* this is to work around broadcom firmware problem to handle
+         * unsolicited command complete event for HCI_LE_Create_Connection_Cancel
+         * and LE connection complete event with status error code (0x2)
+         * unknown connection identifier from bluetooth controller
+         * the workaround is to release the HCI connection to avoid out of sync
+         * with bluetooth controller, which cause BT can't be turned off.
+        */
+        else if ((status == HCI_ERR_NO_CONNECTION) &&
+                 (btm_ble_get_conn_st() != BLE_CONN_CANCEL))
+        {
+            tL2C_LCB    *p_lcb;
+            handle = HCID_GET_HANDLE (handle);
+            p_lcb = l2cu_find_lcb_by_handle (handle);
+            if (p_lcb != NULL)
+            {
+                l2c_link_hci_disc_comp (handle, HCI_ERR_PEER_USER);
+                btm_sec_disconnected (handle, HCI_ERR_PEER_USER);
+            }
+        }
     }
 
     btm_ble_set_conn_st(BLE_CONN_IDLE);
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 47ee8cf..6e4ff9b 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -153,7 +153,7 @@
     tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
     tBTM_STATUS     status = BTM_NO_RESOURCES;
 
-    BTM_TRACE_EVENT0 ("BTM_BleObserve ");
+    BTM_TRACE_EVENT1 ("BTM_BleObserve : scan_type:%d",btm_cb.btm_inq_vars.scan_type);
 
     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
         return BTM_ILLEGAL_VALUE;
@@ -162,10 +162,22 @@
     {
         /* shared inquiry database, do not allow observe if any inquiry is active */
         if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
-            return BTM_BUSY;
-
-        btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb;
-        btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb;
+        {
+            /*check if an interleave scan is already in progress*/
+            if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL
+                && btm_cb.btm_inq_vars.p_inq_results_cb != NULL)
+            {
+                BTM_TRACE_EVENT0 ("BTM_BleObserve general inq in progress, redirecting the results");
+                btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb;
+                btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb;
+                return BTM_SUCCESS;
+            }
+            else
+                return BTM_BUSY;
+        }
+        btm_cb.btm_inq_vars.scan_type = INQ_LE_OBSERVE;
+        btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb;
+        btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb;
         p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
 
         /* allow config scanning type */
@@ -190,10 +202,19 @@
             }
         }
     }
-    else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
+    else/*start = 0*/
     {
-        btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
-        btm_ble_stop_scan();
+        if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL)
+        {
+            //Dont stop the scan. Just nullify the cbs
+            btm_cb.btm_inq_vars.p_inq_ble_results_cb = NULL;
+            btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = NULL;
+        }
+        else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
+        {
+            btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
+            btm_ble_stop_scan();
+        }
     }
 
     return status;
@@ -1540,6 +1561,8 @@
     if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
          (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
     {
+        BTM_TRACE_DEBUG1("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
+                              scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
         p_i->scan_rsp = FALSE;
         to_report = FALSE;
     }
@@ -1669,6 +1692,8 @@
          btm_cb.ble_ctr_cb.p_select_cback == NULL))
         return;
 
+    BTM_TRACE_DEBUG6("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
+                                     bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
     btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
 }
 
@@ -1688,9 +1713,12 @@
 {
     tINQ_DB_ENT          *p_i;
     BOOLEAN              to_report = FALSE;
+    BOOLEAN              to_report_LE = TRUE; //var for reporting to LE observe
     tBTM_INQUIRY_VAR_ST  *p_inq = &btm_cb.btm_inq_vars;
     tBTM_INQ_RESULTS_CB  *p_inq_results_cb = p_inq->p_inq_results_cb;
+    tBTM_INQ_RESULTS_CB  *p_inq_ble_results_cb = p_inq->p_inq_ble_results_cb;
     tBTM_BLE_INQ_CB      *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
+    BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: addr_type: %d, evt_type: %d", addr_type, evt_type);
 
     p_i = btm_inq_db_find (bda);
 
@@ -1710,11 +1738,10 @@
         }
         else
         {
-            /* if yes, skip it */
-            return; /* assumption: one result per event */
+            to_report = FALSE;
         }
     }
-    else /* not been processed int his round */
+    else /* not been processed in this round */
     {
         to_report = TRUE;
     }
@@ -1722,33 +1749,31 @@
     /* If existing entry, use that, else get  a new one (possibly reusing the oldest) */
     if (p_i == NULL)
     {
-        if (btm_ble_is_discoverable(bda, evt_type, p))
+        if ((p_i = btm_inq_db_new (bda)) != NULL)
         {
-            if ((p_i = btm_inq_db_new (bda)) != NULL)
-            {
-                p_inq->inq_cmpl_info.num_resp++;
-                to_report = TRUE;
-            }
-            else
-                return;
+            p_inq->inq_cmpl_info.num_resp++;
+        }
+        else
+            return;
+
+        if (to_report && btm_ble_is_discoverable(bda, evt_type, p))
+        {
+            to_report = TRUE;
         }
         else
         {
             BTM_TRACE_ERROR0("discard adv pkt");
-            return;
+            to_report = FALSE;
         }
     }
     else if (p_i->inq_count != p_inq->inq_counter) /* first time seen in this inquiry */
     {
         p_inq->inq_cmpl_info.num_resp++;
     }
-
     /* update the LE device information in inquiry database */
+    to_report_LE = btm_ble_update_inq_result(p_i, addr_type, evt_type, p);
     if (to_report)
-    {
-        to_report = btm_ble_update_inq_result(p_i, addr_type, evt_type, p);
-    }
-
+        to_report = to_report_LE;
 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
     /* If the number of responses found and limited, issue a cancel inquiry */
     if (p_inq->inqparms.max_resps &&
@@ -1776,6 +1801,8 @@
     }
 #endif
 
+    BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: to_report =%d, to_report_le=%d",
+                                                               to_report, to_report_LE);
     /* background connection in selective connection mode */
     if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
     {
@@ -1787,9 +1814,13 @@
             BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection");
         }
     }
-    else if (p_inq_results_cb && to_report)
+    else if (to_report || to_report_LE)
     {
-        (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+        if(p_inq_results_cb && to_report)
+            (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+        if(p_inq_ble_results_cb && to_report_LE)
+            (p_inq_ble_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results,
+                                                      p_le_inq_cb->adv_data_cache);
     }
 }
 
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index 4c5eecb..24f91a8 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -810,8 +810,8 @@
          */
 #endif
 
-        p_inq->inq_counter++;
-        btm_clr_inq_result_flt();
+         p_inq->inq_counter++;
+         btm_clr_inq_result_flt();
     }
 
     return (status);
@@ -860,7 +860,27 @@
     /* Only one active inquiry is allowed in this implementation.
        Also do not allow an inquiry if the inquiry filter is being updated */
     if (p_inq->inq_active || p_inq->inqfilt_active)
-        return (BTM_BUSY);
+    {
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+        /*check if LE observe is already running*/
+        if(p_inq->scan_type==INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb!=NULL)
+        {
+            BTM_TRACE_API0("BTM_StartInquiry: LE observe in progress");
+            p_inq->scan_type = INQ_GENERAL;
+            p_inq->inq_active = BTM_INQUIRY_INACTIVE;
+            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
+            btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
+            btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+        }
+        else
+#endif
+        {
+            return (BTM_BUSY);
+            BTM_TRACE_API0("BTM_StartInquiry: return BUSY");
+        }
+    }
+    else
+        p_inq->scan_type = INQ_GENERAL;
 
         /*** Make sure the device is ready ***/
     if (!BTM_IsDeviceUp())
@@ -2402,7 +2422,13 @@
     p_inq->inqparms.mode &= ~(mode);
 #endif
 
-
+    if(p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active)
+    {
+        /*end of LE observe*/
+        p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
+        p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
+        p_inq->scan_type=INQ_NONE;
+    }
 
 
 #if (BTM_INQ_DEBUG == TRUE)
@@ -2473,9 +2499,22 @@
                 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
                 /* call the inquiry again */
                 BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
+                return;
             }
 #endif
     }
+    if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete
+    {
+        p_inq->scan_type = INQ_NONE;
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+        /* check if the LE observe is pending */
+        if(p_inq->p_inq_ble_results_cb != NULL)
+        {
+            BTM_TRACE_DEBUG0("BTM Inq Compl: resuming a pending LE scan");
+            BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
+        }
+#endif
+    }
 #if (BTM_INQ_DEBUG == TRUE)
     BTM_TRACE_DEBUG3 ("inq_active:0x%x state:%d inqfilt_active:%d",
         btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 16a02e6..e449d48 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -271,6 +271,14 @@
 } tINQ_DB_ENT;
 
 
+enum
+{
+    INQ_NONE,
+    INQ_LE_OBSERVE,
+    INQ_GENERAL
+};
+typedef UINT8 tBTM_INQ_TYPE;
+
 typedef struct
 {
     tBTM_CMPL_CB *p_remname_cmpl_cb;
@@ -288,6 +296,7 @@
     UINT16           inq_scan_period;
     UINT16           inq_scan_type;
     UINT16           page_scan_type;        /* current page scan type */
+    tBTM_INQ_TYPE    scan_type;
 
     BD_ADDR          remname_bda;           /* Name of bd addr for active remote name request */
 #define BTM_RMT_NAME_INACTIVE       0
@@ -298,6 +307,8 @@
 
     tBTM_CMPL_CB    *p_inq_cmpl_cb;
     tBTM_INQ_RESULTS_CB *p_inq_results_cb;
+    tBTM_CMPL_CB    *p_inq_ble_cmpl_cb;     /*completion callback exclusively for LE Observe*/
+    tBTM_INQ_RESULTS_CB *p_inq_ble_results_cb;/*results callback exclusively for LE observe*/
     tBTM_CMPL_CB    *p_inqfilter_cmpl_cb;   /* Called (if not NULL) after inquiry filter completed */
     tBTM_INQ_DB_CHANGE_CB *p_inq_change_cb; /* Inquiry database changed callback    */
     UINT32           inq_counter;           /* Counter incremented each time an inquiry completes */
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index ab0a0cc..a00466b 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -2269,7 +2269,16 @@
 
 static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
 {
-/* This is empty until an upper layer cares about returning event */
+    /* LE connection update has completed successfully as a master. */
+    /* We can enable the update request if the result is a success. */
+    /* extract the HCI handle first */
+    UINT8   status;
+    UINT16  handle;
+    BT_TRACE_0(TRACE_LAYER_HCI, TRACE_TYPE_EVENT, "btu_ble_ll_conn_param_upd_evt");
+
+    STREAM_TO_UINT8  (status, p);
+    STREAM_TO_UINT16 (handle, p);
+    L2CA_HandleConnUpdateEvent(handle, status);
 }
 
 static void btu_ble_read_remote_feat_evt (UINT8 *p, UINT16 evt_len)
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index 6e3afeb..48f4723 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -65,7 +65,8 @@
     gap_ble_c_cmpl_cback,
     NULL,
     NULL,
-    gap_ble_s_attr_request_cback
+    gap_ble_s_attr_request_cback,
+    NULL
 };
 
 
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index a96c58a..b53b7c5 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -1294,7 +1294,9 @@
 
     gatt_deregister_bgdev_list(gatt_if);
     /* update the listen mode */
+#ifdef BLE_PERIPHERAL_MODE_SUPPORT
     GATT_Listen(gatt_if, FALSE, NULL);
+#endif
 
     memset (p_reg, 0, sizeof(tGATT_REG));
 }
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 459580e..9af6a60 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -48,7 +48,8 @@
     NULL,
     NULL,
     NULL,
-    gatt_profile_request_cback
+    gatt_profile_request_cback,
+    NULL
 } ;
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c
index 504b7d8..e945c90 100644
--- a/stack/gatt/gatt_auth.c
+++ b/stack/gatt/gatt_auth.c
@@ -228,9 +228,18 @@
     tGATT_TCB   *p_tcb;
     tGATT_PENDING_ENC_CLCB  *p_buf;
     UINT16       count;
+    UINT8        i = 0;
 
     if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
     {
+        for (i = 0; i < GATT_MAX_APPS; i++)
+        {
+            if (gatt_cb.cl_rcb[i].in_use && gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)
+            {
+                (*gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)(gatt_cb.cl_rcb[i].gatt_if, bd_addr);
+            }
+        }
+
         if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
         {
             gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 01afb71..d9704b7 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -573,7 +573,8 @@
 /* attribute request callback for ATT server */
 typedef void  (tGATT_REQ_CBACK )(UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data);
 
-
+/* Define a callback function when encryption is established. */
+typedef void (tGATT_ENC_CMPL_CB)(tGATT_IF gatt_if, BD_ADDR bda);
 
 
 /* Define the structure that applications use to register with
@@ -587,6 +588,7 @@
     tGATT_DISC_RES_CB               *p_disc_res_cb;
     tGATT_DISC_CMPL_CB              *p_disc_cmpl_cb;
     tGATT_REQ_CBACK                 *p_req_cb;
+    tGATT_ENC_CMPL_CB               *p_enc_cmpl_cb;
 } tGATT_CBACK;
 
 /***********************  Start Handle Management Definitions   **********************
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 95c44e0..7679d26 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -1146,6 +1146,18 @@
 
 /*******************************************************************************
 **
+** Function         L2CA_HandleConnUpdateEvent
+**
+** Description      This function enables the connection update request from remote
+**                  after a successful connection update response is received.
+**
+** Returns          void
+**
+*******************************************************************************/
+L2C_API void L2CA_HandleConnUpdateEvent (UINT16 handle, UINT8 status);
+
+/*******************************************************************************
+**
 ** Function         L2CA_GetBleConnRole
 **
 ** Description      This function returns the connection role.
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index b8cddd7..a440492 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -81,6 +81,56 @@
         return(FALSE);
 }
 
+/*******************************************************************************
+**
+**  Function        L2CA_InternalBleConnUpdate
+**
+**  Description     update BLE connection based on status
+**
+**  Parameters:     lcb
+**
+**  Return value:   none
+**
+*******************************************************************************/
+static void L2CA_InternalBleConnUpdate (tL2C_LCB *p_lcb)
+{
+    if (p_lcb->upd_status & L2C_BLE_UPDATE_PENDING) return;
+
+    if (p_lcb->upd_status & L2C_BLE_CONN_UPDATE_DISABLE)
+    {
+        /* application requests to disable parameters update.
+           If parameters are already updated, lets set them
+           up to what has been requested during connection establishement */
+        if (p_lcb->upd_status & L2C_BLE_NOT_DEFAULT_PARAM)
+        {
+            tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
+
+            btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle,
+                (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
+                         p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
+                (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
+                         p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
+                (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
+                         p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
+                (UINT16)((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
+                         p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
+                0, 0);
+            p_lcb->upd_status &= ~L2C_BLE_NOT_DEFAULT_PARAM;
+            p_lcb->upd_status |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NEW_CONN_PARAM);
+        }
+    }
+    else
+    {
+        /* application allows to do update, if we were delaying one do it now */
+        if (p_lcb->upd_status & L2C_BLE_NEW_CONN_PARAM)
+        {
+            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->upd_status &= ~L2C_BLE_NEW_CONN_PARAM;
+            p_lcb->upd_status |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NOT_DEFAULT_PARAM);
+        }
+    }
+}
 
 /*******************************************************************************
 **
@@ -116,7 +166,14 @@
     }
 
     if (p_lcb->link_role == HCI_ROLE_MASTER)
-        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int, latency, timeout, 0, 0);
+    {
+        p_lcb->min_interval = min_int;
+        p_lcb->max_interval = max_int;
+        p_lcb->latency = latency;
+        p_lcb->timeout = timeout;
+        p_lcb->upd_status |= L2C_BLE_NEW_CONN_PARAM;
+        L2CA_InternalBleConnUpdate(p_lcb);
+    }
     else
         l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
 
@@ -150,8 +207,9 @@
         return (FALSE);
     }
 
-    L2CAP_TRACE_API4 ("L2CA_EnableUpdateBleConnParams - BD_ADDR %08x%04x enable %d current upd state %d",
-        (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->upd_disabled);
+    L2CAP_TRACE_API4 ("L2CA_EnableUpdateBleConnParams - BD_ADDR %08x%04x enable %d upd state %d",
+        (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5],
+        enable, p_lcb->upd_status);
 
     if (!p_lcb->is_ble_link || (p_lcb->link_role != HCI_ROLE_MASTER))
     {
@@ -162,42 +220,56 @@
 
     if (enable)
     {
-        /* application allows to do update, if we were delaying one do it now, otherwise
-        just mark lcb that updates are enabled */
-        if (p_lcb->upd_disabled == UPD_PENDING)
-        {
-            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->upd_disabled = UPD_UPDATED;
-        }
-        else
-        {
-            p_lcb->upd_disabled = UPD_ENABLED;
-        }
+        p_lcb->upd_status &= ~L2C_BLE_CONN_UPDATE_DISABLE;
     }
     else
     {
-        /* application requests to disable parameters update.  If parameters are already updated, lets set them
-        up to what has been requested during connection establishement */
-        if (p_lcb->upd_disabled == UPD_UPDATED)
-        {
-            tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (rem_bda);
-
-            btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
-                (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
-                (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
-                (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
-                (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
-                0, 0);
-        }
-        p_lcb->upd_disabled = UPD_DISABLED;
+        p_lcb->upd_status |= L2C_BLE_CONN_UPDATE_DISABLE;
     }
 
+    L2CA_InternalBleConnUpdate(p_lcb);
+
     return (TRUE);
 }
 
 /*******************************************************************************
 **
+** Function         L2CA_HandleConnUpdateEvent
+**
+** Description      This function enables the connection update request from remote
+**                  after a successful connection update response is received.
+**
+** Returns          void
+**
+*******************************************************************************/
+void L2CA_HandleConnUpdateEvent (UINT16 handle, UINT8 status)
+{
+    tL2C_LCB *p_lcb;
+
+    L2CAP_TRACE_DEBUG0("L2CA_HandleConnUpdateEvent");
+
+    /* See if we have a link control block for the remote device */
+    p_lcb = l2cu_find_lcb_by_handle(handle);
+    if (!p_lcb)
+    {
+        L2CAP_TRACE_WARNING1("L2CA_EnableUpdateBleConnParams: Invalid handle: %d", handle);
+        return;
+    }
+
+    p_lcb->upd_status &= ~L2C_BLE_UPDATE_PENDING;
+
+    if (status != HCI_SUCCESS)
+    {
+        L2CAP_TRACE_WARNING1("L2CA_EnableUpdateBleConnParams: Error status: %d", status);
+    }
+
+    L2CA_InternalBleConnUpdate(p_lcb);
+
+    L2CAP_TRACE_DEBUG1("L2CA_HandleConnUpdateEvent: upd_status=%d", p_lcb->upd_status);
+}
+
+/*******************************************************************************
+**
 ** Function         L2CA_GetBleConnRole
 **
 ** Description      This function returns the connection role.
@@ -321,6 +393,7 @@
                                            p_dev_rec->conn_params.slave_latency,
                                            p_dev_rec->conn_params.supervision_tout,
                                            0, 0);
+        p_lcb->upd_status |= L2C_BLE_UPDATE_PENDING;
     }
 
     /* Tell BTM Acl management about the link */
@@ -487,18 +560,8 @@
                     p_lcb->max_interval = max_interval;
                     p_lcb->latency = latency;
                     p_lcb->timeout = timeout;
-
-                    if (p_lcb->upd_disabled == UPD_ENABLED)
-                    {
-                        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_interval, max_interval,
-                                                            latency, timeout, 0, 0);
-                        p_lcb->upd_disabled = UPD_UPDATED;
-                    }
-                    else
-                    {
-                        L2CAP_TRACE_EVENT0 ("L2CAP - LE - update currently disabled");
-                        p_lcb->upd_disabled = UPD_PENDING;
-                    }
+                    p_lcb->upd_status |= L2C_BLE_NEW_CONN_PARAM;
+                    L2CA_InternalBleConnUpdate(p_lcb);
                 }
             }
             else
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index a17c583..72d5544 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -435,11 +435,11 @@
     BOOLEAN             is_ble_link;
     tBLE_ADDR_TYPE      ble_addr_type;
 
-#define UPD_ENABLED     0  /* If peer requests update, we will change params */
-#define UPD_DISABLED    1  /* application requested not to update */
-#define UPD_PENDING     2  /* while updates are disabled, peer requested new parameters */
-#define UPD_UPDATED     3  /* peer updated connection parameters */
-    UINT8               upd_disabled;
+#define L2C_BLE_CONN_UPDATE_DISABLE 0x1  /* disable update connection parameters */
+#define L2C_BLE_NEW_CONN_PARAM      0x2  /* new connection parameter to be set */
+#define L2C_BLE_UPDATE_PENDING      0x4  /* waiting for connection update finished */
+#define L2C_BLE_NOT_DEFAULT_PARAM   0x8  /* not using default connection parameters */
+    UINT8               upd_status;
 
     UINT16              min_interval; /* parameters as requested by peripheral */
     UINT16              max_interval;
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 032f3ed..babd300 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -905,10 +905,9 @@
 
     btu_stop_timer (&p_cb->rsp_timer_ent);
 
-    /* if remote user terminate connection, finish SMP pairing as normal */
-    if (p_data->reason == HCI_ERR_PEER_USER)
-        p_cb->status = SMP_SUCCESS;
-    else
+    /* if remote user terminate connection, keep the previous status */
+    /* this is to avoid reporting reverse status to uplayer */
+    if (p_data->reason != HCI_ERR_PEER_USER)
         p_cb->status = SMP_CONN_TOUT;
 
     smp_proc_pairing_cmpl(p_cb);
diff --git a/stack/srvc/srvc_eng.c b/stack/srvc/srvc_eng.c
index a9b466e..d8db1b0 100644
--- a/stack/srvc/srvc_eng.c
+++ b/stack/srvc/srvc_eng.c
@@ -39,7 +39,8 @@
     srvc_eng_c_cmpl_cback,
     NULL,
     NULL,
-    srvc_eng_s_request_cback
+    srvc_eng_s_request_cback,
+    NULL
 } ;
 /* type for action functions */
 typedef void (*tSRVC_ENG_C_CMPL_ACTION)(tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op,