am d6419cd6: am 0a8c803a: am 7f34538a: (-s ours) am 65aec3a3: am 6d429d9d: (-s ours) am 3efb9e2e: DO NOT MERGE Change pairing_cb to assume temporary pairing by default

* commit 'd6419cd6309bd20a2ab095c783bb6ad1f208bf4f':
  DO NOT MERGE Change pairing_cb to assume temporary pairing by default
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c
index 5310ba3..88ac8d6 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.c
+++ b/audio_a2dp_hw/audio_a2dp_hw.c
@@ -1100,10 +1100,8 @@
     int retval = 0;
 
     if (out == NULL)
-    {
-        ERROR("ERROR: set param called even when stream out is null");
         return retval;
-    }
+
     INFO("state %d", out->common.state);
 
     retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 2ef728b..0c0c222 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -1273,14 +1273,29 @@
             p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
             p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
             bta_sys_sendmsg(p_msg);
-
         }
     }
     /* If no Service Search going on then issue cancel remote name in case it is active */
     else if (!bta_dm_search_cb.name_discover_done)
     {
         BTM_CancelRemoteDeviceName();
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
     }
+    else {
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_INQUIRY_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+
 #if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
     if (bta_dm_search_cb.gatt_disc_active)
     {
@@ -4937,8 +4952,8 @@
             else
             {
                 sec_event.auth_cmpl.success = TRUE;
+                GATT_ConfigServiceChangeCCC(bda, TRUE, BT_TRANSPORT_LE);
             }
-            sec_event.auth_cmpl.privacy_enabled = p_data->complt.privacy_supported;
             if (bta_dm_cb.p_sec_cback)
             {
                 //bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index b9403e9..22eab79 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -761,9 +761,6 @@
     LINK_KEY        key;                /* Link key associated with peer device. */
     UINT8           key_type;           /* The type of Link Key */
     BOOLEAN         success;            /* TRUE of authentication succeeded, FALSE if failed. */
-#if BLE_INCLUDED == TRUE
-    BOOLEAN         privacy_enabled;    /* used for BLE device only */
-#endif
     UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
 
 } tBTA_DM_AUTH_CMPL;
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
index d576049..beb2865 100644
--- a/btif/co/bta_dm_co.c
+++ b/btif/co/bta_dm_co.c
@@ -32,7 +32,7 @@
 tBTE_APPL_CFG bte_appl_cfg =
 {
     BTM_AUTH_SPGB_YES,  // Authentication requirements
-    BTM_LOCAL_IO_CAPS,  // I/O capabilities
+    BTM_LOCAL_IO_CAPS_BLE, // I/O capabilities
     7,                  // Initiaor key size
     7,                  // Responder key size
     16                  // Maximum key size
diff --git a/btif/co/bta_gattc_co.c b/btif/co/bta_gattc_co.c
index 8541aa3..5ed7f8f 100644
--- a/btif/co/bta_gattc_co.c
+++ b/btif/co/bta_gattc_co.c
@@ -21,6 +21,7 @@
 #include "bta_gattc_co.h"
 #include "bta_gattc_ci.h"
 #include "btif_util.h"
+#include "btm_int.h"
 
 #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
 #if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
@@ -86,7 +87,7 @@
 {
     /* open NV cache and send call in */
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
-    if (!cacheOpen(server_bda, to_save))
+    if (!btm_sec_is_a_bonded_dev(server_bda) || !cacheOpen(server_bda, to_save))
         status = BTA_GATT_ERROR;
 
     BTIF_TRACE_DEBUG("%s() - status=%d", __FUNCTION__, status);
diff --git a/btif/include/btif_config.h b/btif/include/btif_config.h
index 75a1ac3..2a23a9c 100644
--- a/btif/include/btif_config.h
+++ b/btif/include/btif_config.h
@@ -27,6 +27,9 @@
 #ifndef BTIF_CONFIG_H
 #define BTIF_CONFIG_H
 
+#include "data_types.h"
+#include "bt_types.h"
+
 #ifdef __cplusplus
 #include <stdint.h>
 extern "C" {
@@ -71,6 +74,9 @@
 int btif_config_save();
 void btif_config_flush();
 
+BOOLEAN btif_get_address_type(const BD_ADDR bd_addr, int *p_addr_type);
+BOOLEAN btif_get_device_type(const BD_ADDR bd_addr, int *p_device_type);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/btif/include/btif_gatt_multi_adv_util.h b/btif/include/btif_gatt_multi_adv_util.h
index 1175958..4b44a51 100644
--- a/btif/include/btif_gatt_multi_adv_util.h
+++ b/btif/include/btif_gatt_multi_adv_util.h
@@ -52,7 +52,6 @@
 
 typedef struct
 {
-    UINT8 inst_id;
     BOOLEAN is_scan_rsp;
     UINT8 client_if;
     UINT16 service_uuid_len;
@@ -78,9 +77,12 @@
         BOOLEAN gen_temp_instid);
 extern int btif_multi_adv_instid_for_clientif(int client_if);
 extern int btif_gattc_obtain_idx_for_datacb(int value, int clnt_inst_index);
-extern void btif_gattc_clear_clientif(int client_if);
-extern void btif_gattc_cleanup_inst_cb(int inst_id);
-extern void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_inst_cb);
+extern void btif_gattc_clear_clientif(int client_if, BOOLEAN stop_timer);
+extern void btif_gattc_cleanup_inst_cb(int inst_id, BOOLEAN stop_timer);
+extern void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_inst_cb,
+                                                    BOOLEAN stop_timer);
+// Free a buffer and reset *buf to NULL.
+extern void btif_gattc_cleanup(void** buf);
 extern BOOLEAN btif_gattc_copy_datacb(int arrindex, btif_adv_data_t *p_adv_data,
                                             BOOLEAN bInstData);
 extern void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
diff --git a/btif/include/btif_gatt_util.h b/btif/include/btif_gatt_util.h
index 87c263b..1898317 100644
--- a/btif/include/btif_gatt_util.h
+++ b/btif/include/btif_gatt_util.h
@@ -37,7 +37,5 @@
 
 void btif_gatt_check_encrypted_link(BD_ADDR bd_addr);
 
-BOOLEAN btif_get_device_type(BD_ADDR bd_addr, int *addr_type, int *device_type);
-
 #endif
 
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c
index 7b5ab07..629f4c6 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -44,6 +44,8 @@
 #define LOG_TAG "btif_config"
 
 #include <hardware/bluetooth.h>
+#include "data_types.h"
+#include "bd.h"
 #include "btif_api.h"
 #include "btif_config.h"
 #include "btif_config_util.h"
@@ -362,6 +364,46 @@
         save_cfg();
     unlock_slot(&slot_lock);
 }
+
+/*******************************************************************************
+ * Device information
+ *******************************************************************************/
+BOOLEAN btif_get_device_type(const BD_ADDR bd_addr, int *p_device_type)
+{
+    if (p_device_type == NULL)
+        return FALSE;
+
+    bt_bdaddr_t bda;
+    bdcpy(bda.address, bd_addr);
+
+    char bd_addr_str[18] = {0};
+    bd2str(&bda, &bd_addr_str);
+
+    if (!btif_config_get_int("Remote", bd_addr_str, "DevType", p_device_type))
+        return FALSE;
+
+    ALOGD("%s: Device [%s] type %d", __FUNCTION__, bd_addr_str, *p_device_type);
+    return TRUE;
+}
+
+BOOLEAN btif_get_address_type(const BD_ADDR bd_addr, int *p_addr_type)
+{
+    if (p_addr_type == NULL)
+        return FALSE;
+
+    bt_bdaddr_t bda;
+    bdcpy(bda.address, bd_addr);
+
+    char bd_addr_str[18] = {0};
+    bd2str(&bda, &bd_addr_str);
+
+    if (!btif_config_get_int("Remote", bd_addr_str, "AddrType", p_addr_type))
+        return FALSE;
+
+    ALOGD("%s: Device [%s] address type %d", __FUNCTION__, bd_addr_str, *p_addr_type);
+    return TRUE;
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////////
 static inline short alloc_node(cfg_node* p, short grow)
 {
@@ -944,4 +986,6 @@
     // debug("after removed, btif_config_get ret:%d, Remote devices, 00:22:5F:97:56:04 Class Delete:%s", ret, class);
     // debug("out");
 }
+
+
 #endif
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index 1194c42..1642fb9 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -805,10 +805,15 @@
     bt_bdname_t bd_name;
     UINT32 cod;
     bt_pin_code_t pin_code;
+    int dev_type;
 
     /* Remote properties update */
+    if (!btif_get_device_type(p_pin_req->bd_addr, &dev_type))
+    {
+        dev_type = BT_DEVICE_TYPE_BREDR;
+    }
     btif_update_remote_properties(p_pin_req->bd_addr, p_pin_req->bd_name,
-                                  p_pin_req->dev_class, BT_DEVICE_TYPE_BREDR);
+                                  p_pin_req->dev_class, (tBT_DEVICE_TYPE) dev_type);
 
     bdcpy(bd_addr.address, p_pin_req->bd_addr);
     memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
@@ -885,12 +890,17 @@
     bt_bdname_t bd_name;
     UINT32 cod;
     BOOLEAN is_incoming = !(pairing_cb.state == BT_BOND_STATE_BONDING);
+    int dev_type;
 
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 
     /* Remote properties update */
+    if (!btif_get_device_type(p_ssp_cfm_req->bd_addr, &dev_type))
+    {
+        dev_type = BT_DEVICE_TYPE_BREDR;
+    }
     btif_update_remote_properties(p_ssp_cfm_req->bd_addr, p_ssp_cfm_req->bd_name,
-                                  p_ssp_cfm_req->dev_class, BT_DEVICE_TYPE_BREDR);
+                                  p_ssp_cfm_req->dev_class, (tBT_DEVICE_TYPE) dev_type);
 
     bdcpy(bd_addr.address, p_ssp_cfm_req->bd_addr);
     memcpy(bd_name.name, p_ssp_cfm_req->bd_name, BD_NAME_LEN);
@@ -948,12 +958,17 @@
     bt_bdaddr_t bd_addr;
     bt_bdname_t bd_name;
     UINT32 cod;
+    int dev_type;
 
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 
     /* Remote properties update */
+    if (!btif_get_device_type(p_ssp_key_notif->bd_addr, &dev_type))
+    {
+        dev_type = BT_DEVICE_TYPE_BREDR;
+    }
     btif_update_remote_properties(p_ssp_key_notif->bd_addr, p_ssp_key_notif->bd_name,
-                                  p_ssp_key_notif->dev_class, BT_DEVICE_TYPE_BREDR);
+                                  p_ssp_key_notif->dev_class, (tBT_DEVICE_TYPE) dev_type);
 
     bdcpy(bd_addr.address, p_ssp_key_notif->bd_addr);
     memcpy(bd_name.name, p_ssp_key_notif->bd_name, BD_NAME_LEN);
@@ -1552,7 +1567,7 @@
 
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
              /* Enable local privacy */
-             BTA_DmBleConfigLocalPrivacy(TRUE);
+             BTA_DmBleConfigLocalPrivacy(BLE_LOCAL_PRIVACY_ENABLED);
 #endif
 
              /* for each of the enabled services in the mask, trigger the profile
@@ -2757,12 +2772,17 @@
     bt_bdaddr_t bd_addr;
     bt_bdname_t bd_name;
     UINT32 cod;
+    int dev_type;
 
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 
     /* Remote name update */
-    btif_update_remote_properties(p_ssp_key_notif->bd_addr , p_ssp_key_notif->bd_name,
-                                          NULL, BT_DEVICE_TYPE_BLE);
+    if (!btif_get_device_type(p_ssp_key_notif->bd_addr, &dev_type))
+    {
+        dev_type = BT_DEVICE_TYPE_BLE;
+    }
+    btif_dm_update_ble_remote_properties(p_ssp_key_notif->bd_addr , p_ssp_key_notif->bd_name,
+                                         (tBT_DEVICE_TYPE) dev_type);
     bdcpy(bd_addr.address, p_ssp_key_notif->bd_addr);
     memcpy(bd_name.name, p_ssp_key_notif->bd_name, BD_NAME_LEN);
 
@@ -2952,6 +2972,8 @@
     bt_bdaddr_t bd_addr;
     bt_bdname_t bd_name;
     UINT32 cod;
+    int dev_type;
+
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 
     if (pairing_cb.state == BT_BOND_STATE_BONDING)
@@ -2961,7 +2983,12 @@
     }
 
     /* Remote name update */
-    btif_update_remote_properties(p_ble_req->bd_addr,p_ble_req->bd_name,NULL,BT_DEVICE_TYPE_BLE);
+    if (!btif_get_device_type(p_ble_req->bd_addr, &dev_type))
+    {
+        dev_type = BT_DEVICE_TYPE_BLE;
+    }
+    btif_dm_update_ble_remote_properties(p_ble_req->bd_addr, p_ble_req->bd_name,
+                                         (tBT_DEVICE_TYPE) dev_type);
 
     bdcpy(bd_addr.address, p_ble_req->bd_addr);
     memcpy(bd_name.name, p_ble_req->bd_name, BD_NAME_LEN);
@@ -2994,9 +3021,15 @@
     bt_bdaddr_t bd_addr;
     bt_bdname_t bd_name;
     UINT32 cod;
+    int dev_type;
 
     /* Remote name update */
-    btif_update_remote_properties(p_pin_req->bd_addr,p_pin_req->bd_name,NULL,BT_DEVICE_TYPE_BLE);
+    if (!btif_get_device_type(p_pin_req->bd_addr, &dev_type))
+    {
+        dev_type = BT_DEVICE_TYPE_BLE;
+    }
+    btif_dm_update_ble_remote_properties(p_pin_req->bd_addr,p_pin_req->bd_name,
+                                         (tBT_DEVICE_TYPE) dev_type);
 
     bdcpy(bd_addr.address, p_pin_req->bd_addr);
     memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 5699649..5d37fec 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -660,6 +660,7 @@
         case BTA_GATTC_MULT_ADV_DATA_EVT:
          {
             btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*) p_param;
+            btif_gattc_clear_clientif(p_btif_cb->client_if, FALSE);
             HAL_CBACK(bt_gatt_callbacks, client->multi_adv_data_cb
                 , p_btif_cb->client_if
                 , p_btif_cb->status
@@ -670,7 +671,7 @@
         case BTA_GATTC_MULT_ADV_DIS_EVT:
         {
             btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*) p_param;
-            btif_gattc_clear_clientif(p_btif_cb->client_if);
+            btif_gattc_clear_clientif(p_btif_cb->client_if, TRUE);
             HAL_CBACK(bt_gatt_callbacks, client->multi_adv_disable_cb
                 , p_btif_cb->client_if
                 , p_btif_cb->status
@@ -680,7 +681,7 @@
 
         case BTA_GATTC_ADV_DATA_EVT:
         {
-            btif_gattc_cleanup_inst_cb(STD_ADV_INSTID);
+            btif_gattc_cleanup_inst_cb(STD_ADV_INSTID, FALSE);
             /* No HAL callback available */
             break;
         }
@@ -1092,7 +1093,7 @@
             break;
 
         case BTIF_GATTC_UNREGISTER_APP:
-            btif_gattc_clear_clientif(p_cb->client_if);
+            btif_gattc_clear_clientif(p_cb->client_if, TRUE);
             btif_gattc_decr_app_count();
             BTA_GATTC_AppDeregister(p_cb->client_if);
             break;
@@ -1113,9 +1114,12 @@
             int device_type = 0;
             tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
 
-            if (btif_get_device_type(p_cb->bd_addr.address, &addr_type, &device_type) == TRUE
-                  && device_type != BT_DEVICE_TYPE_BREDR)
+            if (btif_get_address_type(p_cb->bd_addr.address, &addr_type) &&
+                btif_get_device_type(p_cb->bd_addr.address, &device_type) &&
+                device_type != BT_DEVICE_TYPE_BREDR)
+            {
                 BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
+            }
 
             // Mark background connections
             if (!p_cb->is_direct)
@@ -1123,7 +1127,8 @@
                 // Check if RPA offloading is supported, otherwise, do not start
                 // background connection, since it will not connect after address
                 // changes
-                if (BTM_BLE_IS_RESOLVE_BDA(p_cb->bd_addr.address))
+                if ((p_cb->addr_type == BLE_ADDR_RANDOM)
+                        && BTM_BLE_IS_RESOLVE_BDA(p_cb->bd_addr.address))
                 {
                     tBTM_BLE_VSC_CB vnd_capabilities;
                     BTM_BleGetVendorCapabilities(&vnd_capabilities);
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
index 3d7d96c..2a61cc8 100644
--- a/btif/src/btif_gatt_multi_adv_util.c
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -52,13 +52,7 @@
         max_adv_inst = 1;
 
     BTIF_TRACE_DEBUG("%s, Count:%d", __FUNCTION__, max_adv_inst);
-    if(0 == BTM_BleMaxMultiAdvInstanceCount())
-    {
-        BTIF_TRACE_WARNING("BTM_BleMaxMultiAdvInstanceCount - No instances found");
-        return NULL;
-    }
 
-    BTIF_TRACE_DEBUG("BTM_BleMaxMultiAdvInstanceCount count:%d", BTM_BleMaxMultiAdvInstanceCount());
     if (NULL == p_multi_adv_com_data_cb)
     {
         p_multi_adv_com_data_cb = GKI_getbuf(sizeof(btgatt_multi_adv_common_data));
@@ -485,7 +479,7 @@
      return true;
 }
 
-void btif_gattc_clear_clientif(int client_if)
+void btif_gattc_clear_clientif(int client_if, BOOLEAN stop_timer)
 {
     btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
     if (NULL == p_multi_adv_data_cb)
@@ -496,18 +490,20 @@
     {
         if (client_if == p_multi_adv_data_cb->clntif_map[i])
         {
-            btif_gattc_cleanup_inst_cb(p_multi_adv_data_cb->clntif_map[i+1]);
-            p_multi_adv_data_cb->clntif_map[i] = INVALID_ADV_INST;
-            p_multi_adv_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
-            BTIF_TRACE_DEBUG("Cleaning up index %d for clnt_if :%d,", i/2, client_if);
+            btif_gattc_cleanup_inst_cb(p_multi_adv_data_cb->clntif_map[i+1], stop_timer);
+            if (stop_timer)
+            {
+                p_multi_adv_data_cb->clntif_map[i] = INVALID_ADV_INST;
+                p_multi_adv_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
+                BTIF_TRACE_DEBUG("Cleaning up index %d for clnt_if :%d,", i/2, client_if);
+            }
             break;
         }
     }
 }
 
-void btif_gattc_cleanup_inst_cb(int inst_id)
+void btif_gattc_cleanup_inst_cb(int inst_id, BOOLEAN stop_timer)
 {
-    int cbindex = 0;
     // Check for invalid instance id
     if (inst_id < 0 || inst_id >= BTM_BleMaxMultiAdvInstanceCount())
         return;
@@ -516,39 +512,33 @@
     if (NULL == p_multi_adv_data_cb)
         return;
 
-    if (inst_id > 0)
-    {
-        cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
-        if (cbindex < 0)
-            return;
-    } else {
-        if (STD_ADV_INSTID == inst_id)
-          cbindex = STD_ADV_INSTID;
-    }
+    int cbindex = (STD_ADV_INSTID == inst_id) ?
+        STD_ADV_INSTID : btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
+    if (cbindex < 0) return;
 
-    if (inst_id != INVALID_ADV_INST)
-    {
-        BTIF_TRACE_DEBUG("Cleaning up multi_inst_cb for inst_id %d, cbindex %d", inst_id, cbindex);
-        btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex]);
-        p_multi_adv_data_cb->inst_cb[cbindex].inst_id = INVALID_ADV_INST;
-    }
+    BTIF_TRACE_DEBUG("Cleaning up multi_inst_cb for inst_id %d, cbindex %d", inst_id, cbindex);
+    btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex], stop_timer);
 }
 
-void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb)
+void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb,
+                                             BOOLEAN stop_timer)
 {
     if (p_multi_inst_cb == NULL)
         return;
 
     // Discoverability timer cleanup
-    if (p_multi_inst_cb->tle_limited_timer.in_use)
-        btu_stop_timer_oneshot(&p_multi_inst_cb->tle_limited_timer);
+    if (stop_timer)
+    {
+        if (p_multi_inst_cb->tle_limited_timer.in_use)
+            btu_stop_timer_oneshot(&p_multi_inst_cb->tle_limited_timer);
+        p_multi_inst_cb->tle_limited_timer.in_use = 0;
+    }
 
     // Manufacturer data cleanup
     if (p_multi_inst_cb->data.p_manu != NULL)
     {
-        if (p_multi_inst_cb->data.p_manu->p_val != NULL)
-           GKI_freebuf(p_multi_inst_cb->data.p_manu->p_val);
-        GKI_freebuf(p_multi_inst_cb->data.p_manu);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_manu->p_val);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_manu);
     }
 
     // Proprietary data cleanup
@@ -559,58 +549,56 @@
         while (i++ != p_multi_inst_cb->data.p_proprietary->num_elem
             && p_elem)
         {
-            if (p_elem->p_val != NULL)
-                GKI_freebuf(p_elem->p_val);
+            btif_gattc_cleanup((void**) &p_elem->p_val);
             ++p_elem;
         }
 
-        if (p_multi_inst_cb->data.p_proprietary->p_elem != NULL)
-            GKI_freebuf(p_multi_inst_cb->data.p_proprietary->p_elem);
-        GKI_freebuf(p_multi_inst_cb->data.p_proprietary);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_proprietary->p_elem);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_proprietary);
     }
 
     // Service list cleanup
     if (p_multi_inst_cb->data.p_services != NULL)
     {
-        if (p_multi_inst_cb->data.p_services->p_uuid != NULL)
-           GKI_freebuf(p_multi_inst_cb->data.p_services->p_uuid);
-        GKI_freebuf(p_multi_inst_cb->data.p_services);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_services->p_uuid);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_services);
     }
 
     // Service data cleanup
     if (p_multi_inst_cb->data.p_service_data != NULL)
     {
-        if (p_multi_inst_cb->data.p_service_data->p_val != NULL)
-           GKI_freebuf(p_multi_inst_cb->data.p_service_data->p_val);
-        GKI_freebuf(p_multi_inst_cb->data.p_service_data);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_service_data->p_val);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_service_data);
     }
 
-    if (p_multi_inst_cb->data.p_services_128b != NULL)
-        GKI_freebuf(p_multi_inst_cb->data.p_services_128b);
+    btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_services_128b);
 
     if (p_multi_inst_cb->data.p_service_32b != NULL)
     {
-        if (p_multi_inst_cb->data.p_service_32b->p_uuid != NULL)
-           GKI_freebuf(p_multi_inst_cb->data.p_service_32b->p_uuid);
-        GKI_freebuf(p_multi_inst_cb->data.p_service_32b);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_service_32b->p_uuid);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_service_32b);
     }
 
     if (p_multi_inst_cb->data.p_sol_services != NULL)
     {
-        if (p_multi_inst_cb->data.p_sol_services->p_uuid != NULL)
-           GKI_freebuf(p_multi_inst_cb->data.p_sol_services->p_uuid);
-        GKI_freebuf(p_multi_inst_cb->data.p_sol_services);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_sol_services->p_uuid);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_sol_services);
     }
 
     if (p_multi_inst_cb->data.p_sol_service_32b != NULL)
     {
-        if (p_multi_inst_cb->data.p_sol_service_32b->p_uuid != NULL)
-           GKI_freebuf(p_multi_inst_cb->data.p_sol_service_32b->p_uuid);
-        GKI_freebuf(p_multi_inst_cb->data.p_sol_service_32b);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_sol_service_32b->p_uuid);
+        btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_sol_service_32b);
     }
 
-    if (p_multi_inst_cb->data.p_sol_service_128b != NULL)
-        GKI_freebuf(p_multi_inst_cb->data.p_sol_service_128b);
+    btif_gattc_cleanup((void**) &p_multi_inst_cb->data.p_sol_service_128b);
+}
+
+void btif_gattc_cleanup(void** buf)
+{
+   if (NULL == *buf) return;
+   GKI_freebuf(*buf);
+   *buf = NULL;
 }
 
 void btif_multi_adv_timer_ctrl(int client_if, TIMER_CBACK cb)
diff --git a/btif/src/btif_gatt_server.c b/btif/src/btif_gatt_server.c
index 503b5a3..eee0ed1 100644
--- a/btif/src/btif_gatt_server.c
+++ b/btif/src/btif_gatt_server.c
@@ -45,6 +45,7 @@
 #include "bd.h"
 #include "btif_dm.h"
 #include "btif_storage.h"
+#include "btif_config.h"
 
 #include "btif_gatt.h"
 #include "btif_gatt_util.h"
@@ -334,6 +335,12 @@
             break;
 
         case BTA_GATTS_MTU_EVT:
+            HAL_CBACK(bt_gatt_callbacks, server->mtu_changed_cb
+                , p_data->req_data.conn_id
+                , p_data->req_data.p_data->mtu
+            );
+            break;
+
         case BTA_GATTS_OPEN_EVT:
         case BTA_GATTS_CANCEL_OPEN_EVT:
         case BTA_GATTS_CLOSE_EVT:
@@ -384,9 +391,12 @@
             int device_type = 0;
             tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
 
-            if (btif_get_device_type(p_cb->bd_addr.address, &addr_type, &device_type) == TRUE
-                  && device_type != BT_DEVICE_TYPE_BREDR)
+            if (btif_get_address_type(p_cb->bd_addr.address, &addr_type) &&
+                btif_get_device_type(p_cb->bd_addr.address, &device_type) &&
+                device_type != BT_DEVICE_TYPE_BREDR)
+            {
                 BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
+            }
 
             // Mark background connections
             if (!p_cb->is_direct)
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index 348bcea..001fb0b 100644
--- a/btif/src/btif_gatt_util.c
+++ b/btif/src/btif_gatt_util.c
@@ -30,13 +30,13 @@
 #include "bta_jv_api.h"
 #include "bd.h"
 #include "btif_storage.h"
+#include "btif_config.h"
 
 #include "btif_common.h"
 #include "btif_dm.h"
 #include "btif_util.h"
 #include "btif_gatt.h"
 #include "btif_gatt_util.h"
-#include "btif_config.h"
 
 #if BTA_GATT_INCLUDED == TRUE
 
@@ -311,7 +311,6 @@
     bt_bdaddr_t bda;
     bdcpy(bda.address, bd_addr);
     int device_type = 0;
-    int addr_type = 0;
 
 #if (!defined(BLE_DELAY_REQUEST_ENC) || (BLE_DELAY_REQUEST_ENC == FALSE))
     if ((btif_storage_get_ble_bonding_key(&bda, BTIF_DM_LE_KEY_PENC,
@@ -320,7 +319,7 @@
     {
         tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
 
-        btif_get_device_type(bd_addr, &addr_type, &device_type);
+        btif_get_device_type(bd_addr, &device_type);
         switch(device_type)
         {
             case BT_DEVICE_TYPE_BREDR:
@@ -345,29 +344,4 @@
 #endif
 }
 
-/*******************************************************************************
- * Device information
- *******************************************************************************/
-
-BOOLEAN btif_get_device_type(BD_ADDR bd_addr, int *addr_type, int *device_type)
-{
-    if (device_type == NULL || addr_type == NULL)
-        return FALSE;
-
-    bt_bdaddr_t bda;
-    bdcpy(bda.address, bd_addr);
-
-    char bd_addr_str[18] = {0};
-    bd2str(&bda, &bd_addr_str);
-
-    if (!btif_config_get_int("Remote", bd_addr_str, "DevType", device_type))
-        return FALSE;
-
-    if (!btif_config_get_int("Remote", bd_addr_str, "AddrType", addr_type))
-        return FALSE;
-
-    ALOGD("%s: Device [%s] type %d, addr. type %d", __FUNCTION__, bd_addr_str, *device_type, *addr_type);
-    return TRUE;
-}
-
 #endif
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 8336f97..99b0840 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -1711,7 +1711,7 @@
      if (b_enable)
      {
           /* Enable and register with BTA-HH */
-          BTA_HhEnable(BTA_SEC_ENCRYPT, bte_hh_evt);
+          BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt);
      }
      else {
          /* Disable HH */
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index e5ea51a..de34818 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -208,7 +208,10 @@
 
 /* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */
 #define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ 18
-#define MAX_PCM_FRAME_NUM_PER_TICK     10
+
+#ifndef MAX_PCM_FRAME_NUM_PER_TICK
+#define MAX_PCM_FRAME_NUM_PER_TICK     14
+#endif
 
 //#define BTIF_MEDIA_VERBOSE_ENABLED
 /* In case of A2DP SINK, we will delay start by 5 AVDTP Packets*/
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index 32ae984..3d31bf5 100644
--- a/btif/src/btif_pan.c
+++ b/btif/src/btif_pan.c
@@ -703,10 +703,14 @@
                 case -1:
                     BTIF_TRACE_ERROR("%s unable to read from driver: %s", __func__, strerror(errno));
                     GKI_freebuf(buffer);
+                    //add fd back to monitor thread to try it again later
+                    btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0);
                     return;
                 case 0:
                     BTIF_TRACE_WARNING("%s end of file reached.", __func__);
                     GKI_freebuf(buffer);
+                    //add fd back to monitor thread to process the exception
+                    btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0);
                     return;
                 default:
                     btpan_cb.congest_packet_size = ret;
@@ -738,11 +742,11 @@
         ufd.fd = fd;
         ufd.events = POLLIN;
         ufd.revents = 0;
-        if(poll(&ufd, 1, 0) <= 0 || IS_EXCEPTION(ufd.revents)) {
-            btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0);
-            return;
-        }
+        if(poll(&ufd, 1, 0) <= 0 || IS_EXCEPTION(ufd.revents))
+            break;
     }
+    //add fd back to monitor thread
+    btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0);
 }
 
 static void btif_pan_close_all_conns() {
diff --git a/btif/src/btif_sock_util.c b/btif/src/btif_sock_util.c
index 42089ed..8e016e2 100644
--- a/btif/src/btif_sock_util.c
+++ b/btif/src/btif_sock_util.c
@@ -49,8 +49,6 @@
 #include "btif_common.h"
 #include "btif_util.h"
 
-#include "bd.h"
-
 #include "bta_api.h"
 #include "btif_sock_thread.h"
 #include "btif_sock_sdp.h"
diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c
index bd376a6..b86c51a 100644
--- a/btif/src/btif_util.c
+++ b/btif/src/btif_util.c
@@ -51,8 +51,6 @@
 #include "bta_hf_client_api.h"
 #include "avrc_defs.h"
 
-
-
 /************************************************************************************
 **  Constants & Macros
 ************************************************************************************/
@@ -556,5 +554,3 @@
             return "Unknown PDU";
     }
 }
-
-
diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c
index f9151a3..db1409b 100644
--- a/gki/ulinux/gki_ulinux.c
+++ b/gki/ulinux/gki_ulinux.c
@@ -24,6 +24,7 @@
 **              settop projects that already use pthreads and not pth.
 **
 *****************************************************************************/
+#include "bt_target.h"
 
 #include <assert.h>
 #include <sys/times.h>
@@ -95,11 +96,6 @@
 static bool timer_created;
 
 
-// If the next wakeup time is less than this threshold, we should acquire
-// a wakelock instead of setting a wake alarm so we're not bouncing in
-// and out of suspend frequently.
-static const uint32_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 100;
-
 /*****************************************************************************
 **  Externs
 ******************************************************************************/
@@ -153,9 +149,18 @@
 /** Callback from Java thread after alarm from AlarmService fires. */
 static void bt_alarm_cb(void *data)
 {
+    UINT32 ticks_taken = 0;
+
     alarm_service.timer_last_expired_us = now_us();
-    UINT32 ticks_taken = GKI_MS_TO_TICKS((alarm_service.timer_last_expired_us
-                                        - alarm_service.timer_started_us) / 1000);
+    if (alarm_service.timer_last_expired_us > alarm_service.timer_started_us)
+    {
+        ticks_taken = GKI_MS_TO_TICKS((alarm_service.timer_last_expired_us
+                                       - alarm_service.timer_started_us) / 1000);
+    } else {
+        // this could happen on some platform
+        ALOGE("%s now_us %lld less than %lld", __func__, alarm_service.timer_last_expired_us,
+              alarm_service.timer_started_us);
+    }
 
     GKI_timer_update(ticks_taken > alarm_service.ticks_scheduled
                    ? ticks_taken : alarm_service.ticks_scheduled);
@@ -208,7 +213,7 @@
     }
 
     UINT64 ticks_in_millis = GKI_TICKS_TO_MS(ticks_till_next_exp);
-    if (ticks_in_millis <= TIMER_INTERVAL_FOR_WAKELOCK_IN_MS)
+    if (ticks_in_millis <= GKI_TIMER_INTERVAL_FOR_WAKELOCK)
     {
         // The next deadline is close, just take a wakelock and set a regular (non-wake) timer.
         if (!alarm_service.wakelock)
diff --git a/include/bt_target.h b/include/bt_target.h
index a34169a..66b5f98 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -191,6 +191,14 @@
 #define LINUX_GKI_INCLUDED  TRUE
 #endif
 
+// If the next wakeup time is less than this threshold, we should acquire
+// a wakelock instead of setting a wake alarm so we're not bouncing in
+// and out of suspend frequently.
+// in millisecond
+#ifndef GKI_TIMER_INTERVAL_FOR_WAKELOCK
+#define GKI_TIMER_INTERVAL_FOR_WAKELOCK 3000
+#endif
+
 #ifndef BTA_SYS_TIMER_PERIOD
 #define BTA_SYS_TIMER_PERIOD  100
 #endif
@@ -1065,6 +1073,10 @@
 #define BTM_LOCAL_IO_CAPS               BTM_IO_CAP_IO
 #endif
 
+#ifndef BTM_LOCAL_IO_CAPS_BLE
+#define BTM_LOCAL_IO_CAPS_BLE           BTM_IO_CAP_KBDISP
+#endif
+
 /* The default MITM Protection Requirement (for Simple Pairing)
  * Possible values are BTM_AUTH_SP_YES or BTM_AUTH_SP_NO */
 #ifndef BTM_DEFAULT_AUTH_REQ
@@ -1307,10 +1319,25 @@
 #define LOCAL_BLE_CONTROLLER_ID         (1)
 #endif
 
+/*
+ * Toggles support for general LE privacy features such as remote address
+ * resolution, local address rotation etc.
+ */
 #ifndef BLE_PRIVACY_SPT
 #define BLE_PRIVACY_SPT         TRUE
 #endif
 
+/*
+ * Enables or disables support for local privacy (ex. address rotation)
+ */
+#ifndef BLE_LOCAL_PRIVACY_ENABLED
+#define BLE_LOCAL_PRIVACY_ENABLED         TRUE
+#endif
+
+/*
+ * Toggles support for vendor specific extensions such as RPA offloading,
+ * feature discovery, multi-adv etc.
+ */
 #ifndef BLE_VND_INCLUDED
 #define BLE_VND_INCLUDED        FALSE
 #endif
@@ -1430,7 +1457,7 @@
 #endif
 
 #ifndef SMP_DEBUG
-#define SMP_DEBUG            TRUE
+#define SMP_DEBUG            FALSE
 #endif
 
 #ifndef SMP_DEFAULT_AUTH_REQ
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index df852e3..8773036 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -40,17 +40,24 @@
 #define GATTP_ATTR_DB_SIZE      GATT_DB_MEM_SIZE(GATTP_MAX_NUM_INC_SVR, GATTP_MAX_CHAR_NUM, GATTP_MAX_CHAR_VALUE_SIZE)
 #endif
 
-static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
-static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
-                                         BOOLEAN connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport);
+static void gatt_request_cback(UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
+static void gatt_connect_cback(tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected,
+              tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport);
+static void gatt_disc_res_cback(UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
+static void gatt_disc_cmpl_cback(UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
+static void gatt_cl_op_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+              tGATT_CL_COMPLETE *p_data);
+
+static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB *p_clcb);
+
 
 static tGATT_CBACK gatt_profile_cback =
 {
-    gatt_profile_connect_cback,
-    NULL,
-    NULL,
-    NULL,
-    gatt_profile_request_cback,
+    gatt_connect_cback,
+    gatt_cl_op_cmpl_cback,
+    gatt_disc_res_cback,
+    gatt_disc_cmpl_cback,
+    gatt_request_cback,
     NULL,
     NULL
 } ;
@@ -59,25 +66,39 @@
 **
 ** Function         gatt_profile_find_conn_id_by_bd_addr
 **
-** Description      The function searches all LCB with macthing bd address
+** Description      Find the connection ID by remote address
 **
-** Returns          total number of clcb found.
+** Returns          Connection ID
 **
 *******************************************************************************/
-UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda)
+UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR remote_bda)
+{
+    UINT16 conn_id = GATT_INVALID_CONN_ID;
+    GATT_GetConnIdIfConnected (gatt_cb.gatt_if, remote_bda, &conn_id, BT_TRANSPORT_LE);
+    return conn_id;
+}
+
+/*******************************************************************************
+**
+** Function         gatt_profile_find_clcb_by_conn_id
+**
+** Description      find clcb by Connection ID
+**
+** Returns          Pointer to the found link conenction control block.
+**
+*******************************************************************************/
+static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_conn_id(UINT16 conn_id)
 {
     UINT8 i_clcb;
     tGATT_PROFILE_CLCB    *p_clcb = NULL;
 
     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
     {
-        if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
-        {
-            return p_clcb->conn_id;
-        }
+        if (p_clcb->in_use && p_clcb->conn_id == conn_id)
+            return p_clcb;
     }
 
-    return GATT_INVALID_CONN_ID;
+    return p_clcb;
 }
 
 /*******************************************************************************
@@ -98,9 +119,7 @@
     {
         if (p_clcb->in_use && p_clcb->transport == transport &&
             p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
-        {
             return p_clcb;
-        }
     }
 
     return p_clcb;
@@ -134,42 +153,31 @@
     }
     return p_clcb;
 }
+
 /*******************************************************************************
 **
 ** Function         gatt_profile_clcb_dealloc
 **
 ** Description      The function deallocates a GATT profile  connection link control block
 **
-** Returns           NTrue the deallocation is successful
+** Returns          void
 **
 *******************************************************************************/
-BOOLEAN gatt_profile_clcb_dealloc (UINT16 conn_id)
+void gatt_profile_clcb_dealloc (tGATT_PROFILE_CLCB *p_clcb)
 {
-    UINT8                   i_clcb = 0;
-    tGATT_PROFILE_CLCB      *p_clcb = NULL;
-
-    for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
-    {
-        if (p_clcb->in_use && p_clcb->connected && (p_clcb->conn_id == conn_id))
-        {
-            memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
-            return TRUE;
-        }
-    }
-    return FALSE;
+    memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
 }
 
-
 /*******************************************************************************
 **
-** Function         gatt_profile_request_cback
+** Function         gatt_request_cback
 **
 ** Description      GATT profile attribute access request callback.
 **
 ** Returns          void.
 **
 *******************************************************************************/
-static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
+static void gatt_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
                                         tGATTS_DATA *p_data)
 {
     UINT8       status = GATT_INVALID_PDU;
@@ -211,36 +219,40 @@
 
 /*******************************************************************************
 **
-** Function         gatt_profile_connect_cback
+** Function         gatt_connect_cback
 **
 ** Description      Gatt profile connection callback.
 **
 ** Returns          void
 **
 *******************************************************************************/
-static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+static void gatt_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
                                         BOOLEAN connected, tGATT_DISCONN_REASON reason,
                                         tBT_TRANSPORT transport)
 {
     UNUSED(gatt_if);
 
-    GATT_TRACE_EVENT ("gatt_profile_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
+    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 (p_clcb == NULL)
+        return;
+
     if (connected)
     {
-        if (gatt_profile_clcb_alloc(conn_id, bda, transport) == NULL)
-        {
-            GATT_TRACE_ERROR ("gatt_profile_connect_cback: no_resource");
-            return;
-        }
-    }
-    else
-    {
-        gatt_profile_clcb_dealloc(conn_id);
-    }
+        p_clcb->conn_id = conn_id;
+        p_clcb->connected = TRUE;
 
+        if (p_clcb->ccc_stage == GATT_SVC_CHANGED_CONNECTING)
+        {
+            p_clcb->ccc_stage ++;
+            gatt_cl_start_config_ccc(p_clcb);
+        }
+    } else {
+        gatt_profile_clcb_dealloc(p_clcb);
+    }
 }
 
 /*******************************************************************************
@@ -284,4 +296,215 @@
                        gatt_cb.gatt_if,  status);
 }
 
+/*******************************************************************************
+**
+** Function         gatt_config_ccc_complete
+**
+** Description      The function finish the service change ccc configuration
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gatt_config_ccc_complete(tGATT_PROFILE_CLCB *p_clcb)
+{
+    GATT_Disconnect(p_clcb->conn_id);
+    gatt_profile_clcb_dealloc(p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function         gatt_disc_res_cback
+**
+** Description      Gatt profile discovery result callback
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gatt_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
+{
+    tGATT_PROFILE_CLCB *p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL)
+        return;
+
+    switch (disc_type)
+    {
+    case GATT_DISC_SRVC_BY_UUID:/* stage 1 */
+        p_clcb->e_handle = p_data->value.group_value.e_handle;
+        p_clcb->ccc_result ++;
+        break;
+
+    case GATT_DISC_CHAR:/* stage 2 */
+        p_clcb->s_handle = p_data->value.dclr_value.val_handle;
+        p_clcb->ccc_result ++;
+        break;
+
+    case GATT_DISC_CHAR_DSCPT: /* stage 3 */
+        if (p_data->type.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
+        {
+            p_clcb->s_handle = p_data->handle;
+            p_clcb->ccc_result ++;
+        }
+        break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gatt_disc_cmpl_cback
+**
+** Description      Gatt profile discovery complete callback
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gatt_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
+{
+    tGATT_PROFILE_CLCB *p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL)
+        return;
+
+    if (status == GATT_SUCCESS && p_clcb->ccc_result > 0)
+    {
+        p_clcb->ccc_result = 0;
+        p_clcb->ccc_stage ++;
+        gatt_cl_start_config_ccc(p_clcb);
+    } else {
+        GATT_TRACE_ERROR("%s() - Register for service changed indication failure", __FUNCTION__);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gatt_cl_op_cmpl_cback
+**
+** Description      Gatt profile client operation complete callback
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gatt_cl_op_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op,
+                                           tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+    tGATT_PROFILE_CLCB *p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL)
+        return;
+
+    if (op == GATTC_OPTYPE_WRITE)
+    {
+        GATT_TRACE_DEBUG("%s() - ccc write status : %d", __FUNCTION__, status);
+    }
+
+    /* free the connection */
+    gatt_config_ccc_complete (p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function         gatt_cl_start_config_ccc
+**
+** Description      Gatt profile start configure service change CCC
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB *p_clcb)
+{
+    tGATT_DISC_PARAM    srvc_disc_param;
+    tGATT_VALUE         ccc_value;
+
+    GATT_TRACE_DEBUG("%s() - stage: %d", __FUNCTION__, p_clcb->ccc_stage);
+
+    memset (&srvc_disc_param, 0 , sizeof(tGATT_DISC_PARAM));
+    memset (&ccc_value, 0 , sizeof(tGATT_VALUE));
+
+    switch(p_clcb->ccc_stage)
+    {
+    case GATT_SVC_CHANGED_SERVICE: /* discover GATT service */
+        srvc_disc_param.s_handle = 1;
+        srvc_disc_param.e_handle = 0xffff;
+        srvc_disc_param.service.len = 2;
+        srvc_disc_param.service.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER;
+        if (GATTC_Discover (p_clcb->conn_id, GATT_DISC_SRVC_BY_UUID, &srvc_disc_param) != GATT_SUCCESS)
+        {
+            GATT_TRACE_ERROR("%s() - ccc service error", __FUNCTION__);
+            gatt_config_ccc_complete(p_clcb);
+        }
+        break;
+
+    case GATT_SVC_CHANGED_CHARACTERISTIC: /* discover service change char */
+        srvc_disc_param.s_handle = 1;
+        srvc_disc_param.e_handle = p_clcb->e_handle;
+        srvc_disc_param.service.len = 2;
+        srvc_disc_param.service.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
+        if (GATTC_Discover (p_clcb->conn_id, GATT_DISC_CHAR, &srvc_disc_param) != GATT_SUCCESS)
+        {
+            GATT_TRACE_ERROR("%s() - ccc char error", __FUNCTION__);
+            gatt_config_ccc_complete(p_clcb);
+        }
+        break;
+
+    case GATT_SVC_CHANGED_DESCRIPTOR: /* discover service change ccc */
+        srvc_disc_param.s_handle = p_clcb->s_handle;
+        srvc_disc_param.e_handle = p_clcb->e_handle;
+        if (GATTC_Discover (p_clcb->conn_id, GATT_DISC_CHAR_DSCPT, &srvc_disc_param) != GATT_SUCCESS)
+        {
+            GATT_TRACE_ERROR("%s() - ccc char descriptor error", __FUNCTION__);
+            gatt_config_ccc_complete(p_clcb);
+        }
+        break;
+
+    case GATT_SVC_CHANGED_CONFIGURE_CCCD: /* write ccc */
+        ccc_value.handle = p_clcb->s_handle;
+        ccc_value.len = 2;
+        ccc_value.value[0] = GATT_CLT_CONFIG_INDICATION;
+        if (GATTC_Write (p_clcb->conn_id, GATT_WRITE, &ccc_value) != GATT_SUCCESS)
+        {
+            GATT_TRACE_ERROR("%s() - write ccc error", __FUNCTION__);
+            gatt_config_ccc_complete(p_clcb);
+        }
+        break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         GATT_ConfigServiceChangeCCC
+**
+** Description      Configure service change indication on remote device
+**
+** Returns          none
+**
+*******************************************************************************/
+void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable, tBT_TRANSPORT transport)
+{
+    UINT16              conn_id = GATT_INVALID_CONN_ID;
+    tGATT_PROFILE_CLCB   *p_clcb = gatt_profile_find_clcb_by_bd_addr (remote_bda, transport);
+
+    if (p_clcb == NULL)
+        p_clcb = gatt_profile_clcb_alloc (0, remote_bda, transport);
+
+    if (p_clcb == NULL)
+        return;
+
+    if (GATT_GetConnIdIfConnected (gatt_cb.gatt_if, remote_bda, &p_clcb->conn_id, transport))
+    {
+        p_clcb->connected = TRUE;
+    }
+    /* hold the link here */
+    GATT_Connect(gatt_cb.gatt_if, remote_bda, TRUE, transport);
+    p_clcb->ccc_stage = GATT_SVC_CHANGED_CONNECTING;
+
+    if (!p_clcb->connected)
+    {
+        /* wait for connection */
+        return;
+    }
+
+    p_clcb->ccc_stage ++;
+    gatt_cl_start_config_ccc(p_clcb);
+}
+
 #endif  /* BLE_INCLUDED */
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index 0dd3c49..0578086 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -280,7 +280,7 @@
     {
         if (rt != GATT_SUCCESS)
         {
-            GATT_TRACE_ERROR("gatt_act_write() failed op_code=0x%x", op_code);
+            GATT_TRACE_ERROR("gatt_act_write() failed op_code=0x%x rt=%d", op_code, rt);
         }
         gatt_end_operation(p_clcb, rt, NULL);
     }
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 663aa7d..d49c6e1 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -462,6 +462,11 @@
     BOOLEAN         in_use;
 }tGATT_BG_CONN_DEV;
 
+#define GATT_SVC_CHANGED_CONNECTING        1   /* wait for connection */
+#define GATT_SVC_CHANGED_SERVICE           2   /* GATT service discovery */
+#define GATT_SVC_CHANGED_CHARACTERISTIC    3   /* service change char discovery */
+#define GATT_SVC_CHANGED_DESCRIPTOR        4   /* service change CCC discoery */
+#define GATT_SVC_CHANGED_CONFIGURE_CCCD    5   /* config CCC */
 
 typedef struct
 {
@@ -470,6 +475,12 @@
     BOOLEAN connected;
     BD_ADDR bda;
     tBT_TRANSPORT   transport;
+
+    /* GATT service change CCC related variables */
+    UINT8       ccc_stage;
+    UINT8       ccc_result;
+    UINT16      s_handle;
+    UINT16      e_handle;
 }tGATT_PROFILE_CLCB;
 
 typedef struct
@@ -557,8 +568,6 @@
 
 /* from gatt_attr.c */
 extern UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda);
-extern BOOLEAN gatt_profile_clcb_dealloc (UINT16 conn_id);
-extern tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TRANSPORT transport);
 
 
 /* Functions provided by att_protocol.c */
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 392b4b2..2c99c02 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -1169,7 +1169,18 @@
 *******************************************************************************/
     GATT_API extern BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr);
 
-
+/*******************************************************************************
+**
+** Function         GATT_ConfigServiceChangeCCC
+**
+** Description      Configure service change indication on remote device
+**
+** Returns          None.
+**
+*******************************************************************************/
+    GATT_API extern void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable,
+                                                    tBT_TRANSPORT transport);
+ 
 #ifdef __cplusplus
 
 }
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 75a2bfb..d3ba6e2 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -98,62 +98,38 @@
 BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
                                             UINT16 latency, UINT16 timeout)
 {
-        tL2C_LCB            *p_lcb;
-        tACL_CONN           *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
+    tL2C_LCB            *p_lcb;
+    tACL_CONN           *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
 
-        /* See if we have a link control block for the remote device */
-        p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
+    /* See if we have a link control block for the remote device */
+    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
 
-        /* If we don't have one, create one and accept the connection. */
-        if (!p_lcb || !p_acl_cb)
-        {
-            L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
-                                  (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
-                                  (rem_bda[4]<<8)+rem_bda[5]);
-            return(FALSE);
-        }
+    /* If we don't have one, create one and accept the connection. */
+    if (!p_lcb || !p_acl_cb)
+    {
+        L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
+                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+                              (rem_bda[4]<<8)+rem_bda[5]);
+        return(FALSE);
+    }
 
-        if (p_lcb->transport != BT_TRANSPORT_LE)
-        {
-            L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
-                                  (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
-                                  (rem_bda[4]<<8)+rem_bda[5]);
-            return(FALSE);
-        }
-#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
-        /* if both 4.1 compliant */
-        if ((HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) &&
-         HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)))
-        {
-            p_lcb->min_interval = min_int;
-            p_lcb->max_interval = max_int;
-            p_lcb->latency = latency;
-            p_lcb->timeout = timeout;
-            p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
+    if (p_lcb->transport != BT_TRANSPORT_LE)
+    {
+        L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
+                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
+                              (rem_bda[4]<<8)+rem_bda[5]);
+        return(FALSE);
+    }
 
-            l2cble_start_conn_update(p_lcb);
-        }
-        else
-        /* if either side does not support Connection Parameters Request
-        Link Layer Control Procedure,
-           use Link Layer Connection Update procedure */
-#endif
-        {
-            if (p_lcb->link_role == HCI_ROLE_MASTER)
-        {
-            p_lcb->min_interval = min_int;
-            p_lcb->max_interval = max_int;
-            p_lcb->latency = latency;
-            p_lcb->timeout = timeout;
-            p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
+    p_lcb->min_interval = min_int;
+    p_lcb->max_interval = max_int;
+    p_lcb->latency = latency;
+    p_lcb->timeout = timeout;
+    p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
 
-            l2cble_start_conn_update(p_lcb);
-        }
-            else
-                l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
-        }
-        return(TRUE);
+    l2cble_start_conn_update(p_lcb);
 
+    return(TRUE);
 }
 
 
@@ -187,9 +163,9 @@
         (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->conn_update_mask);
 
-    if (p_lcb->transport != BT_TRANSPORT_LE || (p_lcb->link_role != HCI_ROLE_MASTER))
+    if (p_lcb->transport != BT_TRANSPORT_LE)
     {
-        L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE or not master %d", __FUNCTION__,
+        L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
                               (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
                               (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
         return (FALSE);
@@ -330,6 +306,12 @@
     p_lcb->link_role  = HCI_ROLE_MASTER;
     p_lcb->transport  = BT_TRANSPORT_LE;
 
+    /* update link parameter, set slave link as non-spec default upon link up */
+    p_lcb->min_interval =  p_lcb->max_interval = conn_interval;
+    p_lcb->timeout      =  conn_timeout;
+    p_lcb->latency      =  conn_latency;
+    p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
+
     /* If there are any preferred connection parameters, set them now */
     if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
          (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
@@ -348,6 +330,11 @@
                             handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
                             p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
 
+        p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
+        p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
+        p_lcb->timeout      = p_dev_rec->conn_params.supervision_tout;
+        p_lcb->latency      = p_dev_rec->conn_params.slave_latency;
+
         btsnd_hcic_ble_upd_ll_conn_params (handle,
                                            p_dev_rec->conn_params.min_conn_int,
                                            p_dev_rec->conn_params.max_conn_int,
@@ -416,6 +403,12 @@
     p_lcb->link_role  = HCI_ROLE_SLAVE;
     p_lcb->transport  = BT_TRANSPORT_LE;
 
+    /* update link parameter, set slave link as non-spec default upon link up */
+    p_lcb->min_interval = p_lcb->max_interval = conn_interval;
+    p_lcb->timeout      =  conn_timeout;
+    p_lcb->latency      =  conn_latency;
+    p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
+
     /* Tell BTM Acl management about the link */
     p_dev_rec = btm_find_or_alloc_dev (bda);
 
@@ -472,7 +465,9 @@
 *******************************************************************************/
 static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
 {
+    UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
+    tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
 
     if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
 
@@ -481,31 +476,59 @@
         /* 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->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM)
+        if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
+            /* current connection interval is greater than default min */
+            p_lcb->min_interval > BTM_BLE_CONN_INT_MIN)
         {
-            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);
+            /* use 7.5 ms as fast connection parameter, 0 slave latency */
+            min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
+            slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
+            supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
+
+            /* if both side 4.1, or we are master device, send HCI command */
+            if (p_lcb->link_role == HCI_ROLE_MASTER
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+                || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) &&
+                    HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
+#endif
+                 )
+            {
+                btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
+                                                  slave_latency, supervision_tout, 0, 0);
+                p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
+            }
+            else
+            {
+                l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
+            }
             p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
-            p_lcb->conn_update_mask |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NEW_CONN_PARAM);
-        }
+            p_lcb->conn_update_mask |=  L2C_BLE_NEW_CONN_PARAM;
+         }
     }
     else
     {
         /* application allows to do update, if we were delaying one do it now */
         if (p_lcb->conn_update_mask & 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);
+             /* if both side 4.1, or we are master device, send HCI command */
+            if (p_lcb->link_role == HCI_ROLE_MASTER
+#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
+                || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) &&
+                    HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
+#endif
+                 )
+            {
+                btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
+                    p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
+                p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
+            }
+            else
+            {
+                l2cu_send_peer_ble_par_req (p_lcb, p_lcb->min_interval, p_lcb->max_interval,
+                                            p_lcb->latency, p_lcb->timeout);
+            }
             p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
-            p_lcb->conn_update_mask |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NOT_DEFAULT_PARAM);
+            p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
         }
     }
 }
@@ -694,9 +717,9 @@
                                         init_addr,               /* BD_ADDR bda_peer     */
                                         own_addr_type,         /* UINT8 addr_type_own  */
         (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),  /* conn_int_min  */
+        p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
         (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),  /* conn_int_max  */
+        p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
         (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 conn_latency  */
         (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
@@ -929,6 +952,7 @@
         else
         {
             L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
+            p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
             btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL);
         }
 
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
old mode 100644
new mode 100755
index 5f17e91..325f7af
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -267,7 +267,10 @@
              (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb != NULL) )
     {
         /* If no CCB for this channel, allocate one */
-        if (p_lcb && l2cu_initialize_fixed_ccb (p_lcb, rcv_cid,
+        if (p_lcb &&
+            /* discard fixed channel data when link is disconnecting */
+            (p_lcb->link_state != LST_DISCONNECTING) &&
+            l2cu_initialize_fixed_ccb (p_lcb, rcv_cid,
                 &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
         {
 #if(defined BLE_INCLUDED && (BLE_INCLUDED == TRUE))
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index 891d7f8..31313c9 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -81,7 +81,7 @@
     {
         x += sprintf ((char *)&p_buf[x], "%02x ", p[i]);
     }
-    SMP_TRACE_WARNING("%s(LSB ~ MSB) = %s", key_name, p_buf);
+    SMP_TRACE_DEBUG("%s(LSB ~ MSB) = %s", key_name, p_buf);
 }
     #else
         #define smp_debug_print_nbyte_little_endian(p, key_name, len)
@@ -194,7 +194,6 @@
     /* truncate by maximum value */
     while (passkey > BTM_MAX_PASSKEY_VAL)
         passkey >>= 1;
-    SMP_TRACE_ERROR("Passkey generated = %d", passkey);
 
     /* save the TK */
     memset(p_cb->tk, 0, BT_OCTET16_LEN);