am 481b0546: Merge "Fix non-standard pthread mutex interactions."

* commit '481b0546db69274145ee129d19bb03cce4763c6f':
  Fix non-standard pthread mutex interactions.
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 b35ba93..7213866 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -1276,14 +1276,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/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
old mode 100644
new mode 100755
index e79bf1a..546a56f
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -1665,8 +1665,8 @@
 void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
 
-    APPL_TRACE_DEBUG("bta_gattc_ci_load conn_id=%d load status=%d" ,
-                      p_clcb->bta_conn_id, p_data->ci_load.status );
+    APPL_TRACE_DEBUG("bta_gattc_ci_load conn_id=%d load status=%d",
+                      p_clcb->bta_conn_id, p_data->ci_load.status);
 
     if (p_data->ci_load.status == BTA_GATT_OK ||
          p_data->ci_load.status == BTA_GATT_MORE)
@@ -1702,7 +1702,7 @@
 }
 /*******************************************************************************
 **
-** Function         bta_gattc_ci_load
+** Function         bta_gattc_ci_save
 **
 ** Description      cache loading received.
 **
@@ -1791,8 +1791,11 @@
 {
     tBTA_GATTC_DATA *p_buf;
 
-    APPL_TRACE_DEBUG("bta_gattc_conn_cback: cif = %d connected = %d conn_id = %d reaosn = 0x%04x",
-                      gattc_if, connected, conn_id, reason);
+    if (reason != 0)
+    {
+        APPL_TRACE_WARNING("%s() - cif=%d connected=%d conn_id=%d reason=0x%04x",
+                      __FUNCTION__, gattc_if, connected, conn_id, reason);
+    }
 
     if ((p_buf = (tBTA_GATTC_DATA *) GKI_getbuf(sizeof(tBTA_GATTC_DATA))) != NULL)
     {
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index 1ac40da..ac9bb61 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -194,12 +194,12 @@
     BOOLEAN                 in_use;
     UINT8                   inst_id;    /* share service instance ID and report instance ID, as
                                            hi 4 for service instance ID, low 4 as charatceristic instance ID */
-    tBTA_HH_RPT_TYPE	    rpt_type;
+    tBTA_HH_RPT_TYPE        rpt_type;
     UINT16                  uuid;
-    UINT16				    prop;
-    UINT8				    rpt_id;
-    BOOLEAN			        client_cfg_exist;
-    UINT16				    client_cfg_value;
+    UINT8                   prop;
+    UINT8                   rpt_id;
+    BOOLEAN                 client_cfg_exist;
+    UINT16                  client_cfg_value;
 }tBTA_HH_LE_RPT;
 
 #ifndef BTA_HH_LE_RPT_MAX
@@ -209,19 +209,15 @@
 typedef struct
 {
     BOOLEAN                 in_use;
-    tBTA_HH_LE_RPT		    report[BTA_HH_LE_RPT_MAX];
+    tBTA_HH_LE_RPT          report[BTA_HH_LE_RPT_MAX];
 
 #define BTA_HH_LE_PROTO_MODE_BIT        0x01
 #define BTA_HH_LE_CP_BIT                0x02
-    UINT8		            option_char; /* control point char exisit or not */
+    UINT8                   option_char; /* control point char exisit or not */
 
     BOOLEAN                 expl_incl_srvc;
     UINT8                   incl_srvc_inst; /* assuming only one included service : battery service */
     UINT8                   cur_expl_char_idx; /* currently discovering service index */
-
-#define BTA_HH_LE_REMOTE_WAKE   0x01
-#define BTA_HH_LE_NORMAL_CONN   0x02
-    UINT8                   flag;           /* HID Information flag */
     UINT8                   *rpt_map;
     UINT16                  ext_rpt_ref;
     tBTA_HH_DEV_DESCR       descriptor;
@@ -270,6 +266,7 @@
 
     UINT8               disc_active;
     tBTA_HH_STATUS      status;
+    tBTA_GATT_REASON    reason;
     BOOLEAN             is_le_device;
     tBTA_HH_LE_HID_SRVC hid_srvc[BTA_HH_LE_HID_SRVC_MAX];
     UINT16              conn_id;
@@ -408,6 +405,7 @@
 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);
+extern void bta_hh_ci_load_rpt (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
 
 #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 ed43449..df541af 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -81,6 +81,9 @@
 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond);
+static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
+                                      tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
+                                      UINT8 num_rpt);
 
 #define BTA_HH_LE_SRVC_DEF      0
 
@@ -149,6 +152,7 @@
             break;
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_uuid_to_str
@@ -188,6 +192,7 @@
             return "Unknown UUID";
     }
 }
+
 #endif
 /*******************************************************************************
 **
@@ -219,6 +224,7 @@
 
     return;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_register_cmpl
@@ -289,6 +295,7 @@
 
     return p_cb->is_le_device;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_add_hid_srvc_entry
@@ -312,8 +319,8 @@
         APPL_TRACE_ERROR("DB full,max HID service entry!");
     }
     return added;
-
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_open_conn
@@ -333,6 +340,7 @@
 
     BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, TRUE, BTA_GATT_TRANSPORT_LE);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_fill_16bits_gatt_id
@@ -346,6 +354,7 @@
     p_output->uuid.len       = LEN_UUID_16;
     p_output->uuid.uu.uuid16 = uuid;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_fill_16bits_srvc_id
@@ -362,6 +371,7 @@
     bta_hh_le_fill_16bits_gatt_id(inst_id, srvc_uuid, &p_output->id);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_fill_16bits_char_id
@@ -376,6 +386,7 @@
     memset((void *)p_output, 0, sizeof(tBTA_GATT_ID));
     bta_hh_le_fill_16bits_gatt_id(inst_id, char_uuid, p_output);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_find_dev_cb_by_conn_id
@@ -395,6 +406,7 @@
     }
     return NULL;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_find_dev_cb_by_bda
@@ -437,6 +449,7 @@
     }
     return BTA_HH_IDX_INVALID;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_find_report_entry
@@ -476,6 +489,7 @@
     return NULL;
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_find_rpt_by_idtype
@@ -513,6 +527,7 @@
     }
     return NULL;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_find_alloc_report_entry
@@ -569,7 +584,6 @@
                     }
                 }
             }
-
             return p_rpt;
         }
     }
@@ -618,6 +632,7 @@
     }
     return status;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_read_rpt_ref_descr
@@ -682,6 +697,7 @@
         bta_hh_le_search_hid_chars(p_dev_cb);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_save_rpt_ref
@@ -694,7 +710,8 @@
 void bta_hh_le_save_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT  *p_rpt,
                             tBTA_GATTC_READ *p_data)
 {
-    UINT8 *pp;
+    UINT8                       *pp;
+    tBTA_HH_RPT_CACHE_ENTRY     rpt_entry;
 
     /* if the length of the descriptor value is right, parse it */
     if (p_data->status == BTA_GATT_OK &&
@@ -711,16 +728,35 @@
 #if BTA_HH_DEBUG == TRUE
         APPL_TRACE_DEBUG("report ID: %d", p_rpt->rpt_id);
 #endif
+        rpt_entry.rpt_id    = p_rpt->rpt_id;
+        rpt_entry.rpt_type  = p_rpt->rpt_type;
+        rpt_entry.rpt_uuid  = p_rpt->uuid;
+        rpt_entry.prop      = p_rpt->prop;
+        rpt_entry.inst_id   = p_rpt->inst_id;
+
+        bta_hh_le_co_rpt_info(p_dev_cb->addr,
+                              &rpt_entry,
+                              p_dev_cb->app_id);
+    }
+    else if (p_data->status == BTA_GATT_INSUF_AUTHENTICATION)
+    {
+        /* close connection right away */
+        p_dev_cb->status = BTA_HH_ERR_AUTH_FAILED;
+        /* close the connection and report service discovery complete with error */
+        bta_hh_le_api_disc_act(p_dev_cb);
+        return;
     }
 
     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);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_save_rpt_ref
@@ -751,6 +787,7 @@
     bta_hh_le_search_hid_chars(p_dev_cb);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_register_input_notif
@@ -855,6 +892,7 @@
 #endif
         bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, TRUE);
         bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
+
 #if (BTA_HH_LE_RECONN == TRUE)
         if (p_cb->status == BTA_HH_OK)
         {
@@ -863,6 +901,7 @@
 #endif
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_write_char_clt_cfg
@@ -908,6 +947,7 @@
     }
     return FALSE;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_write_rpt_clt_cfg
@@ -970,7 +1010,7 @@
 {
     tBTA_GATTC_CHAR_ID  char_id;
     tBTA_HH_CBDATA      cback_data ;
-    BOOLEAN             exec = TRUE;
+    BOOLEAN             exec = FALSE;
 
     APPL_TRACE_DEBUG("bta_hh_le_set_protocol_mode attempt mode: %s",
                       (mode == BTA_HH_PROTO_RPT_MODE)? "Report": "Boot");
@@ -979,7 +1019,6 @@
     /* boot mode is not supported in the remote device */
     if ((p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].option_char & BTA_HH_LE_PROTO_MODE_BIT) == 0)
     {
-        exec        = FALSE;
         p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
 
         if (mode == BTA_HH_PROTO_BOOT_MODE)
@@ -1000,7 +1039,7 @@
         else
             (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
     }
-    else
+    else if (p_cb->mode != mode)
     {
         bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
         bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
@@ -1014,7 +1053,9 @@
                                  1,
                                  &mode,
                                  BTA_GATT_AUTH_REQ_NONE);
+        exec        = TRUE;
     }
+
     return exec;
 }
 
@@ -1058,6 +1099,7 @@
     }
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_expl_rpt
@@ -1104,6 +1146,7 @@
 
     return ;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_expl_boot_rpt
@@ -1126,6 +1169,7 @@
 
     return;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_dis_cback
@@ -1162,6 +1206,7 @@
     }
     bta_hh_le_open_cmpl(p_cb);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_pri_service_discovery
@@ -1176,6 +1221,8 @@
 {
     tBT_UUID        pri_srvc;
 
+    bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
+
     p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS|BTA_HH_LE_DISC_DIS);
 
     /* read DIS info */
@@ -1192,6 +1239,7 @@
     BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
     return;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_encrypt_cback
@@ -1217,9 +1265,11 @@
         return;
     }
     p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
+    p_dev_cb->reason = result;
 
     bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_security_cmpl
@@ -1232,10 +1282,22 @@
 *******************************************************************************/
 void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
 {
+    tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
+    UINT8                       num_rpt = 0;
     UNUSED(p_buf);
 
     if (p_cb->status == BTA_HH_OK)
     {
+        APPL_TRACE_DEBUG("bta_hh_security_cmpl OK");
+        if (!p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
+        {
+            APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
+            /* start loading the cache if not in stack */
+            if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL)
+            {
+                bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
+            }
+        }
         /*  discovery has been done for HID service */
         if (p_cb->app_id != 0 && p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
         {
@@ -1253,8 +1315,12 @@
         }
     }
     else
-        bta_hh_le_api_disc_act(p_cb);
-
+    {
+        APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
+                __FUNCTION__, p_cb->status, p_cb->reason);
+        if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING))
+            bta_hh_le_api_disc_act(p_cb);
+    }
 }
 
 /*******************************************************************************
@@ -1282,7 +1348,7 @@
 **
 ** Function         bta_hh_clear_service_cache
 **
-** Description    clear the service cache
+** Description      clear the service cache
 **
 ** Parameters:
 **
@@ -1361,6 +1427,7 @@
 
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_gatt_open
@@ -1388,7 +1455,7 @@
 
     if (p_data->status == BTA_GATT_OK)
     {
-
+        p_cb->is_le_device  = TRUE;
         p_cb->in_use    = TRUE;
         p_cb->conn_id   = p_data->conn_id;
         p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
@@ -1408,6 +1475,7 @@
     }
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_close
@@ -1528,9 +1596,7 @@
     {
         if (!p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc)
             /* explore included service first */
-            {
-                bta_hh_le_search_hid_included(p_dev_cb);
-            }
+            bta_hh_le_search_hid_included(p_dev_cb);
         else
         {
             /* explore characterisc */
@@ -1543,6 +1609,7 @@
         bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_srvc_search_cmpl
@@ -1610,7 +1677,6 @@
                             &inc_srvc_result) == BTA_GATT_OK)
     {
         /* read include service UUID */
-
         p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].incl_srvc_inst = inc_srvc_result.incl_svc_id.id.inst_id;
 
         char_cond.len = LEN_UUID_16;
@@ -1623,6 +1689,7 @@
                                     &char_result,
                                     &prop) == BTA_GATT_OK)
         {
+
             if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
                                                   char_result.srvc_id.id.inst_id,
                                                   GATT_UUID_BATTERY_LEVEL,
@@ -1651,6 +1718,7 @@
     bta_hh_le_srvc_expl_srvc(p_dev_cb);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_read_battery_level_cmpl
@@ -1761,6 +1829,7 @@
         bta_hh_le_search_hid_chars(p_dev_cb);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_save_rpt_map
@@ -1800,9 +1869,8 @@
     {
         bta_hh_le_search_hid_chars(p_dev_cb);
     }
-
-
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_proc_get_rpt_cmpl
@@ -1859,8 +1927,8 @@
     (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
 
     utl_freebuf((void **)&p_buf);
-
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_proc_read_proto_mode
@@ -1899,6 +1967,7 @@
     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_w4_le_read_char_cmpl
@@ -1960,6 +2029,7 @@
     }
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_read_char_cmpl
@@ -1994,6 +2064,7 @@
     }
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_read_descr_cmpl
@@ -2051,9 +2122,9 @@
         }
         else
             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
-
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_w4_le_read_descr_cmpl
@@ -2137,6 +2208,7 @@
         }
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_write_cmpl
@@ -2195,6 +2267,7 @@
     }
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_write_char_descr_cmpl
@@ -2210,7 +2283,7 @@
     UINT8   srvc_inst_id, hid_inst_id;
 
     /* only write client configuration possible */
-    if (p_data && p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
+    if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
     {
         srvc_inst_id = p_data->srvc_id.id.inst_id;
         hid_inst_id = srvc_inst_id;
@@ -2223,9 +2296,9 @@
         case GATT_UUID_HID_BT_MOUSE_INPUT:
         case GATT_UUID_HID_REPORT:
             if (p_data->status == BTA_GATT_OK)
-                p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx ++].client_cfg_value =
+                p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx].client_cfg_value =
                         BTA_GATT_CLT_CONFIG_NOTIFICATION;
-
+            p_dev_cb->clt_cfg_idx ++;
             bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
 
             break;
@@ -2233,6 +2306,7 @@
         case GATT_UUID_SCAN_REFRESH:
             bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
             break;
+
         default:
             APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", p_data->char_id.uuid.uu.uuid16);
         }
@@ -2249,6 +2323,7 @@
     }
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_input_rpt_notify
@@ -2270,7 +2345,6 @@
         APPL_TRACE_ERROR("notification received from Unknown device");
         return;
     }
-
     app_id= p_dev_cb->app_id;
 
     p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
@@ -2319,7 +2393,6 @@
         GKI_freebuf(p_buf);
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_hh_gatt_open_fail
@@ -2355,6 +2428,7 @@
     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_gatt_close
@@ -2396,6 +2470,7 @@
     return;
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_api_disc_act
@@ -2408,7 +2483,12 @@
 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
 {
     if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
+    {
         BTA_GATTC_Close(p_cb->conn_id);
+        /* remove device from background connection if intended to disconnect,
+           do not allow reconnection */
+        bta_hh_le_remove_dev_bg_conn(p_cb);
+    }
 }
 
 /*******************************************************************************
@@ -2496,6 +2576,7 @@
                              BTA_GATT_AUTH_REQ_NONE);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_suspend
@@ -2588,8 +2669,8 @@
             APPL_TRACE_ERROR("unsupported trsanction for LE HID device: %d", p_data->api_sndcmd.t_type);
             break;
     }
-
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_get_dscp_act
@@ -2707,6 +2788,7 @@
         BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_update_scpp
@@ -2752,6 +2834,7 @@
                              BTA_GATT_AUTH_REQ_NONE);
 
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_gattc_callback
@@ -2884,6 +2967,7 @@
 
     return;
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_search_scps
@@ -2910,6 +2994,7 @@
     else
         bta_hh_le_open_cmpl(p_cb);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_search_scps_chars
@@ -2968,7 +3053,7 @@
         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0)
     {
-        BTM_GetSecurityFlags(p_dev_cb->addr, &sec_flag);
+        BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE);
         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
         {
             if (bta_hh_le_write_char_clt_cfg (p_dev_cb,
@@ -2990,6 +3075,7 @@
     }
     bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_le_register_scpp_notif_cmpl
@@ -3014,6 +3100,60 @@
 
 
 }
+
+/*******************************************************************************
+**
+** Function         bta_hh_process_cache_rpt
+**
+** Description      Process the cached reports
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
+                                      tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
+                                      UINT8 num_rpt)
+{
+    UINT8                       i = 0;
+    tBTA_HH_LE_RPT              *p_rpt;
+
+    if (num_rpt != 0)  /* no cache is found */
+    {
+        p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].in_use = TRUE;
+
+        /* set the descriptor info */
+        p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dl_len =
+                p_cb->dscp_info.descriptor.dl_len;
+        p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dsc_list =
+                    p_cb->dscp_info.descriptor.dsc_list;
+
+        for (; i <num_rpt; i ++, p_rpt_cache ++)
+        {
+            if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
+                                               BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id),
+                                               p_rpt_cache->rpt_uuid,
+                                               BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt_cache->inst_id),
+                                               p_rpt_cache->prop))  == NULL)
+            {
+                APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
+                break;
+            }
+            else
+            {
+                p_rpt->rpt_type =  p_rpt_cache->rpt_type;
+                p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
+
+                if(p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
+                    p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
+                    (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT))
+                {
+                    p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
+                }
+            }
+        }
+    }
+}
+
 #endif
 
 
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index bfc880e..aef2606 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/bta/include/bta_hh_co.h b/bta/include/bta_hh_co.h
old mode 100644
new mode 100755
index 8f648df..bf73b46
--- a/bta/include/bta_hh_co.h
+++ b/bta/include/bta_hh_co.h
@@ -26,6 +26,14 @@
 
 #include "bta_hh_api.h"
 
+typedef struct
+{
+    UINT16              rpt_uuid;
+    UINT8               rpt_id;
+    tBTA_HH_RPT_TYPE    rpt_type;
+    UINT8               inst_id;
+    UINT8               prop;
+}tBTA_HH_RPT_CACHE_ENTRY;
 
 /*******************************************************************************
 **
@@ -68,5 +76,59 @@
 *******************************************************************************/
 BTA_API extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id);
 
+#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_rpt_info
+**
+** Description      This callout function is to convey the report information on
+**                  a HOGP device to the application. Application can save this
+**                  information in NV if device is bonded and load it back when
+**                  stack reboot.
+**
+** Parameters       remote_bda  - remote device address
+**                  p_entry     - report entry pointer
+**                  app_id      - application id
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_le_co_rpt_info(BD_ADDR remote_bda,
+                                          tBTA_HH_RPT_CACHE_ENTRY *p_entry,
+                                          UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_cache_load
+**
+** Description      This callout function is to request the application to load the
+**                  cached HOGP report if there is any. When cache reading is completed,
+**                  bta_hh_le_ci_cache_load() is called by the application.
+**
+** Parameters       remote_bda  - remote device address
+**                  p_num_rpt: number of cached report
+**                  app_id      - application id
+**
+** Returns          the acched report array
+**
+*******************************************************************************/
+BTA_API extern tBTA_HH_RPT_CACHE_ENTRY *bta_hh_le_co_cache_load (BD_ADDR remote_bda,
+                                                                 UINT8 *p_num_rpt,
+                                                                 UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_reset_rpt_cache
+**
+** Description      This callout function is to reset the HOGP device cache.
+**
+** Parameters       remote_bda  - remote device address
+**
+** Returns          none
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_le_co_reset_rpt_cache (BD_ADDR remote_bda, UINT8 app_id);
+
+#endif /* #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */
 #endif /* BTA_HH_CO_H */
 
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/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index 0701955..d7458b1 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -31,10 +31,15 @@
 #include "bta_api.h"
 #include "bta_hh_api.h"
 #include "btif_util.h"
-
+#include "bta_hh_co.h"
 
 const char *dev_path = "/dev/uhid";
 
+#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE)
+#include "btif_config.h"
+#define BTA_HH_NV_LOAD_MAX       16
+static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
+#endif
 
 /*Internal function to perform UHID write and error checking*/
 static int uhid_write(int fd, const struct uhid_event *ev)
@@ -341,7 +346,6 @@
             break;
         }
      }
-
 }
 
 
@@ -446,4 +450,118 @@
     }
 }
 
+#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_rpt_info
+**
+** Description      This callout function is to convey the report information on
+**                  a HOGP device to the application. Application can save this
+**                  information in NV if device is bonded and load it back when
+**                  stack reboot.
+**
+** Parameters       remote_bda  - remote device address
+**                  p_entry     - report entry pointer
+**                  app_id      - application id
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_hh_le_co_rpt_info(BD_ADDR remote_bda, tBTA_HH_RPT_CACHE_ENTRY *p_entry, UINT8 app_id)
+{
+    UNUSED(app_id);
+
+    unsigned len = 0;
+    unsigned type = 0;
+    unsigned idx = 0;
+
+    bdstr_t bdstr;
+    sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
+        remote_bda[0], remote_bda[1], remote_bda[2],
+        remote_bda[3], remote_bda[4], remote_bda[5]);
+
+    btif_config_get("Remote", bdstr, "HidReport", NULL, (int*)&len, (int*)&type);
+    if (len >= sizeof(tBTA_HH_RPT_CACHE_ENTRY) && len <= sizeof(sReportCache))
+    {
+        btif_config_get("Remote", bdstr, "HidReport", (char*)sReportCache, (int*)&len, (int*)&type);
+        idx = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY);
+    }
+
+    if (idx < BTA_HH_NV_LOAD_MAX)
+    {
+        memcpy(&sReportCache[idx++], p_entry, sizeof(tBTA_HH_RPT_CACHE_ENTRY));
+        btif_config_set("Remote", bdstr, "HidReport", (const char*)sReportCache,
+            idx * sizeof(tBTA_HH_RPT_CACHE_ENTRY), BTIF_CFG_TYPE_BIN);
+        BTIF_TRACE_DEBUG("%s() - Saving report; dev=%s, idx=%d", __FUNCTION__, bdstr, idx);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_cache_load
+**
+** Description      This callout function is to request the application to load the
+**                  cached HOGP report if there is any. When cache reading is completed,
+**                  bta_hh_le_ci_cache_load() is called by the application.
+**
+** Parameters       remote_bda  - remote device address
+**                  p_num_rpt: number of cached report
+**                  app_id      - application id
+**
+** Returns          the acched report array
+**
+*******************************************************************************/
+tBTA_HH_RPT_CACHE_ENTRY * bta_hh_le_co_cache_load (BD_ADDR remote_bda,
+                                                   UINT8 *p_num_rpt, UINT8 app_id)
+{
+    UNUSED(app_id);
+
+    unsigned len = 0;
+    unsigned type = 0;
+    unsigned idx = 0;
+
+    bdstr_t bdstr;
+    sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
+        remote_bda[0], remote_bda[1], remote_bda[2],
+        remote_bda[3], remote_bda[4], remote_bda[5]);
+
+    btif_config_get("Remote", bdstr, "HidReport", NULL, (int*)&len, (int*)&type);
+    if (!p_num_rpt && len < sizeof(tBTA_HH_RPT_CACHE_ENTRY))
+        return NULL;
+
+    if (len > sizeof(sReportCache))
+        len = sizeof(sReportCache);
+    btif_config_get("Remote", bdstr, "HidReport", (char*)sReportCache, (int*)&len, (int*)&type);
+    *p_num_rpt = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY);
+
+    BTIF_TRACE_DEBUG("%s() - Loaded %d reports; dev=%s", __FUNCTION__, *p_num_rpt, bdstr);
+
+    return sReportCache;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_reset_rpt_cache
+**
+** Description      This callout function is to reset the HOGP device cache.
+**
+** Parameters       remote_bda  - remote device address
+**
+** Returns          none
+**
+*******************************************************************************/
+void bta_hh_le_co_reset_rpt_cache (BD_ADDR remote_bda, UINT8 app_id)
+{
+    UNUSED(app_id);
+
+    bdstr_t bdstr;
+    sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
+        remote_bda[0], remote_bda[1], remote_bda[2],
+        remote_bda[3], remote_bda[4], remote_bda[5]);
+    btif_config_remove("Remote", bdstr, "HidReport");
+
+    BTIF_TRACE_DEBUG("%s() - Reset cache for bda %s", __FUNCTION__, bdstr);
+}
+#endif /* #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */
 
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_dm.h b/btif/include/btif_dm.h
index 37f11b7..297e2a9 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -92,12 +92,19 @@
 
 typedef struct
 {
+    BT_OCTET16          irk;
+    tBLE_ADDR_TYPE      addr_type;
+    BD_ADDR             static_addr;
+}btif_dm_ble_pid_keys_t;
+
+typedef struct
+{
     BOOLEAN                   is_penc_key_rcvd;
     btif_dm_ble_penc_keys_t   penc_key;       /* received peer encryption key */
     BOOLEAN                   is_pcsrk_key_rcvd;
     btif_dm_ble_pcsrk_keys_t  pcsrk_key;       /* received peer device SRK */
     BOOLEAN                   is_pid_key_rcvd;
-    UINT8                     pid_key[BT_OCTET16_LEN];        /* peer device ID key */
+    btif_dm_ble_pid_keys_t    pid_key;        /* peer device ID key */
     BOOLEAN                   is_lenc_key_rcvd;
     btif_dm_ble_lenc_keys_t   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
     BOOLEAN                   is_lcsrk_key_rcvd;
diff --git a/btif/include/btif_gatt_multi_adv_util.h b/btif/include/btif_gatt_multi_adv_util.h
index e6c26a0..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;
@@ -72,15 +71,18 @@
 } btgatt_multi_adv_common_data;
 
 extern btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb();
-extern void btif_gattc_init_multi_adv_cb(void);
-extern void btif_gattc_destroy_multi_adv_cb();
+extern void btif_gattc_incr_app_count(void);
+extern void btif_gattc_decr_app_count(void);
 extern int btif_multi_adv_add_instid_map(int client_if, int inst_id,
         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 a10ec80..eb69f7d 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"
@@ -361,6 +363,46 @@
         save_cfg();
     pthread_mutex_unlock(&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)
 {
@@ -939,4 +981,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 c8e1bac..f3592f1 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -111,11 +111,15 @@
 
 #define MAX_SDP_BL_ENTRIES 3
 
+#define BOND_TYPE_UNKNOWN     0
+#define BOND_TYPE_PERSISTENT  1
+#define BOND_TYPE_TEMPORARY   2
+
 typedef struct
 {
     bt_bond_state_t state;
     BD_ADDR bd_addr;
-    UINT8   is_temp;
+    UINT8   bond_type;
     UINT8   pin_code_len;
     UINT8   is_ssp;
     UINT8   auth_req;
@@ -469,7 +473,7 @@
     if ( (pairing_cb.state == state) && (state == BT_BOND_STATE_BONDING) )
         return;
 
-    if (pairing_cb.is_temp)
+    if (pairing_cb.bond_type == BOND_TYPE_TEMPORARY)
     {
        state = BT_BOND_STATE_NONE;
     }
@@ -800,10 +804,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);
@@ -880,12 +889,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);
@@ -897,9 +911,9 @@
     if (p_ssp_cfm_req->just_works && !(p_ssp_cfm_req->loc_auth_req & BTM_AUTH_BONDS) &&
         !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS) &&
         !(check_cod((bt_bdaddr_t*)&p_ssp_cfm_req->bd_addr, COD_HID_POINTING)))
-        pairing_cb.is_temp = TRUE;
+        pairing_cb.bond_type = BOND_TYPE_TEMPORARY;
     else
-        pairing_cb.is_temp = FALSE;
+        pairing_cb.bond_type = BOND_TYPE_PERSISTENT;
 
     pairing_cb.is_ssp = TRUE;
 
@@ -943,12 +957,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);
@@ -987,11 +1006,11 @@
     if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) )
     {
         if ((p_auth_cmpl->key_type < HCI_LKEY_TYPE_DEBUG_COMB)  || (p_auth_cmpl->key_type == HCI_LKEY_TYPE_AUTH_COMB) ||
-            (p_auth_cmpl->key_type == HCI_LKEY_TYPE_CHANGED_COMB) || (!pairing_cb.is_temp))
+            (p_auth_cmpl->key_type == HCI_LKEY_TYPE_CHANGED_COMB) || pairing_cb.bond_type == BOND_TYPE_PERSISTENT)
         {
             bt_status_t ret;
-            BTIF_TRACE_DEBUG("%s: Storing link key. key_type=0x%x, is_temp=%d",
-                __FUNCTION__, p_auth_cmpl->key_type, pairing_cb.is_temp);
+            BTIF_TRACE_DEBUG("%s: Storing link key. key_type=0x%x, bond_type=%d",
+                __FUNCTION__, p_auth_cmpl->key_type, pairing_cb.bond_type);
             ret = btif_storage_add_bonded_device(&bd_addr,
                                 p_auth_cmpl->key, p_auth_cmpl->key_type,
                                 pairing_cb.pin_code_len);
@@ -999,9 +1018,9 @@
         }
         else
         {
-            BTIF_TRACE_DEBUG("%s: Temporary key. Not storing. key_type=0x%x, is_temp=%d",
-                __FUNCTION__, p_auth_cmpl->key_type, pairing_cb.is_temp);
-            if(pairing_cb.is_temp)
+            BTIF_TRACE_DEBUG("%s: Temporary key. Not storing. key_type=0x%x, bond_type=%d",
+                __FUNCTION__, p_auth_cmpl->key_type, pairing_cb.bond_type);
+            if(pairing_cb.bond_type == BOND_TYPE_TEMPORARY)
             {
                 BTIF_TRACE_DEBUG("%s: sending BT_BOND_STATE_NONE for Temp pairing",
                         __FUNCTION__);
@@ -1542,7 +1561,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
@@ -1717,10 +1736,19 @@
                 case BTA_LE_KEY_PID:
                     BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PID");
                     pairing_cb.ble.is_pid_key_rcvd = TRUE;
-                    memcpy(pairing_cb.ble.pid_key, p_data->ble_key.key_value.pid_key.irk, 16);
+                    pairing_cb.ble.pid_key.addr_type = p_data->ble_key.key_value.pid_key.addr_type;
+                    memcpy(pairing_cb.ble.pid_key.irk, p_data->ble_key.key_value.pid_key.irk, 16);
+                    memcpy(pairing_cb.ble.pid_key.static_addr,
+                            p_data->ble_key.key_value.pid_key.static_addr,BD_ADDR_LEN);
                     for (i=0; i<16; i++)
                     {
-                        BTIF_TRACE_DEBUG("pairing_cb.ble.pid_key[%d]=0x%02x",i,pairing_cb.ble.pid_key[i]);
+                        BTIF_TRACE_DEBUG("pairing_cb.ble.pid_key.irk[%d]=0x%02x"
+                                            ,i,pairing_cb.ble.pid_key.irk[i]);
+                    }
+                    for (i=0; i<BD_ADDR_LEN; i++)
+                    {
+                        BTIF_TRACE_DEBUG("piaring_cb.ble.pid_address[%d] = %x"
+                                            ,i, pairing_cb.ble.pid_key.static_addr[i]);
                     }
                     break;
 
@@ -2736,12 +2764,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);
 
@@ -2870,9 +2903,9 @@
     if (pairing_cb.ble.is_pid_key_rcvd)
     {
         btif_storage_add_ble_bonding_key(&bd_addr,
-                                         (char *) &pairing_cb.ble.pid_key[0],
+                                         (char *) &pairing_cb.ble.pid_key,
                                          BTIF_DM_LE_KEY_PID,
-                                         BT_OCTET16_LEN);
+                                         sizeof(btif_dm_ble_pid_keys_t));
     }
 
 
@@ -2929,6 +2962,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)
@@ -2938,14 +2973,19 @@
     }
 
     /* 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);
 
     bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
 
-    pairing_cb.is_temp = FALSE;
+    pairing_cb.bond_type = BOND_TYPE_PERSISTENT;
     pairing_cb.is_le_only = TRUE;
     pairing_cb.is_ssp = TRUE;
 
@@ -2971,9 +3011,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 de55146..1bd12c2 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -659,6 +659,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
@@ -669,7 +670,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
@@ -679,7 +680,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;
         }
@@ -1086,13 +1087,13 @@
     {
         case BTIF_GATTC_REGISTER_APP:
             btif_to_bta_uuid(&uuid, &p_cb->uuid);
-            btif_gattc_init_multi_adv_cb();
+            btif_gattc_incr_app_count();
             BTA_GATTC_AppRegister(&uuid, bta_gattc_cback);
             break;
 
         case BTIF_GATTC_UNREGISTER_APP:
-            btif_gattc_clear_clientif(p_cb->client_if);
-            btif_gattc_destroy_multi_adv_cb();
+            btif_gattc_clear_clientif(p_cb->client_if, TRUE);
+            btif_gattc_decr_app_count();
             BTA_GATTC_AppDeregister(p_cb->client_if);
             break;
 
@@ -1112,9 +1113,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)
@@ -1122,7 +1126,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
old mode 100755
new mode 100644
index 5d2556f..30d02db
--- a/btif/src/btif_gatt_multi_adv_util.c
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -43,21 +43,19 @@
 /*******************************************************************************
 **  Static variables
 ********************************************************************************/
-static int multi_adv_enable_count = 0;
+static int user_app_count = 0;
 static btgatt_multi_adv_common_data *p_multi_adv_com_data_cb = NULL;
 
 btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
 {
-    if(0 == BTM_BleMaxMultiAdvInstanceCount())
-    {
-        BTIF_TRACE_WARNING("%s - No instances found", __FUNCTION__);
-        return NULL;
-    }
+    int max_adv_inst = BTM_BleMaxMultiAdvInstanceCount();
+    if (0 == max_adv_inst)
+        max_adv_inst = 1;
 
-    BTIF_TRACE_DEBUG("%s, Count:%d", __FUNCTION__, BTM_BleMaxMultiAdvInstanceCount());
+    BTIF_TRACE_DEBUG("%s, Count:%d", __FUNCTION__, max_adv_inst);
+
     if (NULL == p_multi_adv_com_data_cb)
     {
-        BTIF_TRACE_DEBUG("Initializing in %s", __FUNCTION__);
         p_multi_adv_com_data_cb = GKI_getbuf(sizeof(btgatt_multi_adv_common_data));
         if (NULL != p_multi_adv_com_data_cb)
         {
@@ -65,16 +63,16 @@
 
             /* Storing both client_if and inst_id details */
             p_multi_adv_com_data_cb->clntif_map =
-                  GKI_getbuf(( BTM_BleMaxMultiAdvInstanceCount() * INST_ID_IDX_MAX)* sizeof(INT8));
+                  GKI_getbuf(( max_adv_inst * INST_ID_IDX_MAX)* sizeof(INT8));
             memset(p_multi_adv_com_data_cb->clntif_map, 0 ,
-                  ( BTM_BleMaxMultiAdvInstanceCount() * INST_ID_IDX_MAX)* sizeof(INT8));
+                  ( max_adv_inst * INST_ID_IDX_MAX)* sizeof(INT8));
 
-            p_multi_adv_com_data_cb->inst_cb = GKI_getbuf(( BTM_BleMaxMultiAdvInstanceCount() + 1 )
+            p_multi_adv_com_data_cb->inst_cb = GKI_getbuf(( max_adv_inst + 1 )
                                               * sizeof(btgatt_multi_adv_inst_cb));
             memset(p_multi_adv_com_data_cb->inst_cb, 0 ,
-                 ( BTM_BleMaxMultiAdvInstanceCount() + 1) * sizeof(btgatt_multi_adv_inst_cb));
+                 ( max_adv_inst + 1) * sizeof(btgatt_multi_adv_inst_cb));
 
-            for (int i=0; i < BTM_BleMaxMultiAdvInstanceCount()*2; i += 2)
+            for (int i=0; i < max_adv_inst * 2; i += 2)
             {
                 p_multi_adv_com_data_cb->clntif_map[i] = INVALID_ADV_INST;
                 p_multi_adv_com_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
@@ -85,27 +83,24 @@
     return p_multi_adv_com_data_cb;
 }
 
-void btif_gattc_init_multi_adv_cb(void)
+void btif_gattc_incr_app_count(void)
 {
     // TODO: Instead of using a fragile reference counter here, one could
     //       simply track the client_if instances that are in the map.
-    ++multi_adv_enable_count;
+    ++user_app_count;
 }
 
-void btif_gattc_destroy_multi_adv_cb(int client_if)
+void btif_gattc_decr_app_count(void)
 {
-    if (multi_adv_enable_count > 0)
-        multi_adv_enable_count --;
+    if (user_app_count > 0)
+        user_app_count --;
 
-    if(multi_adv_enable_count == 0 && p_multi_adv_com_data_cb != 0)
+    if(user_app_count == 0 && NULL != p_multi_adv_com_data_cb)
     {
-        if (NULL != p_multi_adv_com_data_cb)
-        {
-            GKI_freebuf (p_multi_adv_com_data_cb->clntif_map);
-            GKI_freebuf (p_multi_adv_com_data_cb->inst_cb);
-            GKI_freebuf(p_multi_adv_com_data_cb);
-            p_multi_adv_com_data_cb = NULL;
-        }
+       GKI_freebuf (p_multi_adv_com_data_cb->clntif_map);
+       GKI_freebuf (p_multi_adv_com_data_cb->inst_cb);
+       GKI_freebuf(p_multi_adv_com_data_cb);
+       p_multi_adv_com_data_cb = NULL;
     }
 }
 
@@ -484,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)
@@ -495,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;
@@ -515,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
@@ -558,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 9e317ef..03c208c 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
 
@@ -48,8 +48,6 @@
     0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-extern bt_status_t btif_dm_remove_bond(const bt_bdaddr_t *bd_addr);
-
 int uuidType(unsigned char* p_uuid)
 {
     int i = 0;
@@ -296,14 +294,12 @@
 
 static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_STATUS result)
 {
+    UNUSED(bd_addr);
     UNUSED(transport);
 
     if (result != BTA_SUCCESS && result != BTA_BUSY)
     {
-        bt_bdaddr_t bda;
-        bdcpy(bda.address, bd_addr);
-
-        btif_dm_remove_bond(&bda);
+        BTIF_TRACE_WARNING("%s() - Encryption failed (%d)", __FUNCTION__, result);
     }
 }
 
@@ -314,7 +310,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,
@@ -323,7 +318,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:
@@ -348,29 +343,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 b7d041e..176643e 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -915,10 +915,8 @@
             break;
 
         case BTA_HH_GET_DSCP_EVT:
-            BTIF_TRACE_WARNING("BTA_HH_GET_DSCP_EVT: status = %d, handle = %d",
-                p_data->dev_status.status, p_data->dev_status.handle);
-                len = p_data->dscp_info.descriptor.dl_len;
-                BTIF_TRACE_DEBUG("BTA_HH_GET_DSCP_EVT: len = %d", len);
+            len = p_data->dscp_info.descriptor.dl_len;
+            BTIF_TRACE_DEBUG("BTA_HH_GET_DSCP_EVT: len = %d", len);
             p_dev = btif_hh_cb.p_curr_dev;
             if (p_dev == NULL) {
                 BTIF_TRACE_ERROR("BTA_HH_GET_DSCP_EVT: No HID device is currently connected");
@@ -1709,7 +1707,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 88ca6d4..7908996 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -208,9 +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 A2DP_PACKET_COUNT_LOW_WATERMARK 5
-#define MAX_PCM_FRAME_NUM_PER_TICK     10
-#define RESET_RATE_COUNTER_THRESHOLD_MS    2000
+
+#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*/
@@ -247,10 +248,6 @@
     INT32  aa_feed_residue;
     UINT32 counter;
     UINT32 bytes_per_tick;  /* pcm bytes read each media task tick */
-    UINT32 max_counter_exit;
-    UINT32 max_counter_enter;
-    UINT32 overflow_count;
-    BOOLEAN overflow;
 } tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE;
 
 
@@ -2353,11 +2350,6 @@
  *******************************************************************************/
 static void btif_media_task_feeding_state_reset(void)
 {
-    APPL_TRACE_WARNING("overflow %d, enter %d, exit %d",
-        btif_media_cb.media_feeding_state.pcm.overflow_count,
-        btif_media_cb.media_feeding_state.pcm.max_counter_enter,
-        btif_media_cb.media_feeding_state.pcm.max_counter_exit);
-
     /* By default, just clear the entire state */
     memset(&btif_media_cb.media_feeding_state, 0, sizeof(btif_media_cb.media_feeding_state));
 
@@ -2440,12 +2432,12 @@
  *******************************************************************************/
 static UINT8 btif_get_num_aa_frame(void)
 {
-    UINT32 result=0;
+    UINT8 result=0;
 
     switch (btif_media_cb.TxTranscoding)
     {
         case BTIF_MEDIA_TRSCD_PCM_2_SBC:
-           {
+        {
             UINT32 pcm_bytes_per_frame = btif_media_cb.encoder.s16NumOfSubBands *
                              btif_media_cb.encoder.s16NumOfBlocks *
                              btif_media_cb.media_feeding.cfg.pcm.num_channel *
@@ -2460,29 +2452,16 @@
             btif_media_cb.media_feeding_state.pcm.counter +=
                                 btif_media_cb.media_feeding_state.pcm.bytes_per_tick *
                                 us_this_tick / (BTIF_MEDIA_TIME_TICK * 1000);
-            if ((!btif_media_cb.media_feeding_state.pcm.overflow) ||
-                (btif_media_cb.TxAaQ.count < A2DP_PACKET_COUNT_LOW_WATERMARK)) {
-                if (btif_media_cb.media_feeding_state.pcm.overflow) {
-                    btif_media_cb.media_feeding_state.pcm.overflow = FALSE;
 
-                    if (btif_media_cb.media_feeding_state.pcm.counter >
-                        btif_media_cb.media_feeding_state.pcm.max_counter_exit) {
-                        btif_media_cb.media_feeding_state.pcm.max_counter_exit =
-                            btif_media_cb.media_feeding_state.pcm.counter;
-                    }
-                }
-                /* calculate nbr of frames pending for this media tick */
-                result = btif_media_cb.media_feeding_state.pcm.counter/pcm_bytes_per_frame;
-                if (result > MAX_PCM_FRAME_NUM_PER_TICK)
-                {
-                    APPL_TRACE_ERROR("%s() - Limiting frames to be sent from %d to %d"
-                        , __FUNCTION__, result, MAX_PCM_FRAME_NUM_PER_TICK);
-                    result = MAX_PCM_FRAME_NUM_PER_TICK;
-                }
-                btif_media_cb.media_feeding_state.pcm.counter -= result*pcm_bytes_per_frame;
-            } else {
-                result = 0;
+            /* calculate nbr of frames pending for this media tick */
+            result = btif_media_cb.media_feeding_state.pcm.counter/pcm_bytes_per_frame;
+            if (result > MAX_PCM_FRAME_NUM_PER_TICK)
+            {
+                APPL_TRACE_WARNING("%s() - Limiting frames to be sent from %d to %d"
+                    , __FUNCTION__, result, MAX_PCM_FRAME_NUM_PER_TICK);
+                result = MAX_PCM_FRAME_NUM_PER_TICK;
             }
+            btif_media_cb.media_feeding_state.pcm.counter -= result*pcm_bytes_per_frame;
 
             VERBOSE("WRITE %d FRAMES", result);
         }
@@ -2842,32 +2821,6 @@
         {
             GKI_freebuf(p_buf);
         }
-
-        if (btif_media_cb.TxAaQ.count >= MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) {
-            UINT32 reset_rate_bytes = btif_media_cb.media_feeding_state.pcm.bytes_per_tick *
-                                (RESET_RATE_COUNTER_THRESHOLD_MS / BTIF_MEDIA_TIME_TICK);
-            btif_media_cb.media_feeding_state.pcm.overflow = TRUE;
-            btif_media_cb.media_feeding_state.pcm.counter += nb_frame *
-                     btif_media_cb.encoder.s16NumOfSubBands *
-                     btif_media_cb.encoder.s16NumOfBlocks *
-                     btif_media_cb.media_feeding.cfg.pcm.num_channel *
-                     btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
-
-            btif_media_cb.media_feeding_state.pcm.overflow_count++;
-            if (btif_media_cb.media_feeding_state.pcm.counter >
-                btif_media_cb.media_feeding_state.pcm.max_counter_enter) {
-                btif_media_cb.media_feeding_state.pcm.max_counter_enter =
-                    btif_media_cb.media_feeding_state.pcm.counter;
-            }
-
-            if (btif_media_cb.media_feeding_state.pcm.counter > reset_rate_bytes) {
-                btif_media_cb.media_feeding_state.pcm.counter = 0;
-                APPL_TRACE_WARNING("btif_media_aa_prep_sbc_2_send:reset rate counter");
-            }
-
-            /* no more pcm to read */
-            nb_frame = 0;
-        }
     }
 }
 
@@ -2884,8 +2837,16 @@
 
 static void btif_media_aa_prep_2_send(UINT8 nb_frame)
 {
-    VERBOSE("btif_media_aa_prep_2_send : %d frames (queue %d)", nb_frame,
-                       btif_media_cb.TxAaQ.count);
+    VERBOSE("%s() - frames=%d (queue=%d)", __FUNCTION__, nb_frame, btif_media_cb.TxAaQ.count);
+
+    while (btif_media_cb.TxAaQ.count >= (MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ-nb_frame))
+    {
+        APPL_TRACE_WARNING("%s() - TX queue buffer count %d",
+            __FUNCTION__, btif_media_cb.TxAaQ.count);
+        GKI_freebuf(GKI_dequeue(&(btif_media_cb.TxAaQ)));
+    }
+
+    if (btif_media_cb.TxAaQ.count) --nb_frame;
 
     switch (btif_media_cb.TxTranscoding)
     {
@@ -2916,7 +2877,8 @@
     /* get the number of frame to send */
     nb_frame_2_send = btif_get_num_aa_frame();
 
-    if (nb_frame_2_send != 0) {
+    if (nb_frame_2_send != 0)
+    {
         /* format and Q buffer to send */
         btif_media_aa_prep_2_send(nb_frame_2_send);
     }
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index 1f75b1d..5a0a0ce 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_storage.c b/btif/src/btif_storage.c
index 55e6a26..d9898cb 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -1222,7 +1222,7 @@
             if (btif_storage_get_ble_bonding_key(&bd_addr,
                                                  BTIF_DM_LE_KEY_PID,
                                                  buf,
-                                                 sizeof(btif_dm_ble_pcsrk_keys_t)) == BT_STATUS_SUCCESS)
+                                                 sizeof(btif_dm_ble_pid_keys_t)) == BT_STATUS_SUCCESS)
             {
                 if(add)
                 {
@@ -1234,7 +1234,14 @@
                     p = (tBTA_LE_KEY_VALUE *)buf;
                     for (i=0; i<16; i++)
                     {
-                        BTIF_TRACE_DEBUG("p->pid_key[%d]=0x%02x",i,p->pid_key.irk[i]);
+                        BTIF_TRACE_DEBUG("p->pid_key.irk[%d]=0x%02x"
+                                            ,i,p->pid_key.irk[i]);
+                    }
+                    BTIF_TRACE_DEBUG("p->pid_key.addr_type=%d",p->pid_key.addr_type);
+                    for (i=0; i<BD_ADDR_LEN; i++)
+                    {
+                        BTIF_TRACE_DEBUG("p->pid_key.static_addr[%d]=%02x"
+                                            ,i,p->pid_key.static_addr[i]);
                     }
 
                     BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PID);
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/common/gki_buffer.c b/gki/common/gki_buffer.c
index 16b6ce3..1d176b3 100644
--- a/gki/common/gki_buffer.c
+++ b/gki/common/gki_buffer.c
@@ -408,7 +408,10 @@
 // btla-specific ++
         #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
             if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE)
+            {
+                GKI_enable();
                 return NULL;
+            }
         #endif
 // btla-specific --
             p_hdr = Q->p_first;
@@ -475,7 +478,10 @@
 // btla-specific ++
 #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
         if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE)
+        {
+            GKI_enable();
             return NULL;
+        }
 #endif
 // btla-specific --
         p_hdr = Q->p_first;
diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c
index 167ab88..422d59f 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 <errno.h>
@@ -98,11 +99,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 = 3000;
-
 /*****************************************************************************
 **  Externs
 ******************************************************************************/
@@ -156,9 +152,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);
@@ -211,16 +216,19 @@
     }
 
     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.
-        int rc = bt_os_callouts->acquire_wake_lock(WAKE_LOCK_ID);
-        if (rc != BT_STATUS_SUCCESS)
+        if (!alarm_service.wakelock)
         {
-            ALOGE("%s unable to acquire wake lock: %d", __func__, rc);
-            return;
+            int rc = bt_os_callouts->acquire_wake_lock(WAKE_LOCK_ID);
+            if (rc != BT_STATUS_SUCCESS)
+            {
+                ALOGE("%s unable to acquire wake lock: %d", __func__, rc);
+                return;
+            }
+            alarm_service.wakelock = true;
         }
-        alarm_service.wakelock = true;
         ALOGV("%s acquired wake lock, setting short alarm (%lldms).", __func__, ticks_in_millis);
 
         if (!set_nonwake_alarm(ticks_in_millis))
@@ -237,8 +245,12 @@
         } else {
             ALOGV("%s set long alarm (%lldms), releasing wake lock.", __func__, ticks_in_millis);
         }
-        alarm_service.wakelock = false;
-        bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
+
+        if (alarm_service.wakelock)
+        {
+            alarm_service.wakelock = false;
+            bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
+        }
     }
 }
 
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/btm/btm_ble.c b/stack/btm/btm_ble.c
index 860be14..1552c4e 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -1614,9 +1614,6 @@
 
     if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM && !addr_matched)
         memcpy(p_dev_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
-
-    if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
-        btm_ble_vendor_disable_irk_list();
 #endif
 
     if (role == HCI_ROLE_SLAVE)
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index 28a1db8..b33aa2e 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -76,7 +76,7 @@
     tBT_DEVICE_TYPE dev_type;
 
     if (p_dev_rec != NULL &&
-        p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+        p_dev_rec->device_type & BT_DEVICE_TYPE_BLE)
     {
 
         if (to_add)
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index e523d5b..902c776 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -642,16 +642,12 @@
 
     if (match_rec)
     {
-        BTM_TRACE_ERROR("Random match");
+        BTM_TRACE_DEBUG("Random match");
         match_rec->ble.active_addr_type = BTM_BLE_ADDR_RRA;
         memcpy(match_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
         memcpy(bda, match_rec->bd_addr, BD_ADDR_LEN);
         addr_type = match_rec->ble.ble_addr_type;
     }
-    else
-    {
-        BTM_TRACE_ERROR("Random unmatch");
-    }
 
     btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, pp);
 
@@ -2435,7 +2431,7 @@
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
     /* map address to security record */
     btm_public_addr_to_random_pseudo(bda, &addr_type);
-    BTM_TRACE_ERROR("new address: %02x:%02x:%02x:%02x:%02x:%02x",
+    BTM_TRACE_DEBUG("new address: %02x:%02x:%02x:%02x:%02x:%02x",
                      bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
 #endif
 
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 05e3084..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,63 @@
 **
 ** 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;
+}
+
+/*******************************************************************************
+**
+** Function         gatt_profile_find_clcb_by_bd_addr
+**
+** Description      The function searches all LCBs with macthing bd address.
+**
+** Returns          Pointer to the found link conenction control block.
+**
+*******************************************************************************/
+static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda, tBT_TRANSPORT transport)
+{
+    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->transport == transport &&
+            p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+            return p_clcb;
+    }
+
+    return p_clcb;
 }
 
 /*******************************************************************************
@@ -108,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;
@@ -185,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);
+    }
 }
 
 /*******************************************************************************
@@ -258,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 a132775..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) ?
@@ -836,7 +859,7 @@
     if (num_lowpri_links > low_quota)
     {
         l2cb.ble_round_robin_quota = low_quota;
-        qq = qq_remainder = 0;
+        qq = qq_remainder = 1;
     }
     /* If each low priority link can have at least one buffer */
     else if (num_lowpri_links > 0)
@@ -851,7 +874,7 @@
     {
         l2cb.ble_round_robin_quota = 0;
         l2cb.ble_round_robin_unacked = 0;
-        qq = qq_remainder = 0;
+        qq = qq_remainder = 1;
     }
     L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation  num_hipri: %u  num_lowpri: %u  low_quota: %u  round_robin_quota: %u  qq: %u",
                         num_hipri_links, num_lowpri_links, low_quota,
@@ -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_link.c b/stack/l2cap/l2c_link.c
index aa8f66c..5ee5faa 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -743,7 +743,7 @@
     if (num_lowpri_links > low_quota)
     {
         l2cb.round_robin_quota = low_quota;
-        qq = qq_remainder = 0;
+        qq = qq_remainder = 1;
     }
     /* If each low priority link can have at least one buffer */
     else if (num_lowpri_links > 0)
@@ -758,7 +758,7 @@
     {
         l2cb.round_robin_quota = 0;
         l2cb.round_robin_unacked = 0;
-        qq = qq_remainder = 0;
+        qq = qq_remainder = 1;
     }
 
     L2CAP_TRACE_EVENT ("l2c_link_adjust_allocation  num_hipri: %u  num_lowpri: %u  low_quota: %u  round_robin_quota: %u  qq: %u",
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
old mode 100644
new mode 100755
index 4563e8a..c2531a7
--- 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 316679c..ec7d129 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -66,7 +66,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)
@@ -179,7 +179,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);
diff --git a/udrv/ulinux/uipc.c b/udrv/ulinux/uipc.c
index a0b8e2a..db58a21 100644
--- a/udrv/ulinux/uipc.c
+++ b/udrv/ulinux/uipc.c
@@ -69,6 +69,8 @@
 
 #define SAFE_FD_ISSET(fd, set) (((fd) == -1) ? FALSE : FD_ISSET((fd), (set)))
 
+#define UIPC_FLUSH_BUFFER_SIZE 1024
+
 /*****************************************************************************
 **  Local type definitions
 ******************************************************************************/
@@ -375,30 +377,40 @@
 
 static void uipc_flush_ch_locked(tUIPC_CH_ID ch_id)
 {
-    char buf;
+    char buf[UIPC_FLUSH_BUFFER_SIZE];
     struct pollfd pfd;
     int ret;
 
-    pfd.events = POLLIN|POLLHUP;
+    pfd.events = POLLIN;
     pfd.fd = uipc_main.ch[ch_id].fd;
 
     if (uipc_main.ch[ch_id].fd == UIPC_DISCONNECTED)
+    {
+        BTIF_TRACE_EVENT("%s() - fd disconnected. Exiting", __FUNCTION__);
         return;
+    }
 
     while (1)
     {
         ret = poll(&pfd, 1, 1);
-        BTIF_TRACE_EVENT("uipc_flush_ch_locked polling : fd %d, rxev %x, ret %d", pfd.fd, pfd.revents, ret);
+        BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d",
+                __FUNCTION__, pfd.fd, pfd.revents, ret);
 
         if (pfd.revents & (POLLERR|POLLHUP))
+        {
+            BTIF_TRACE_EVENT("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__);
             return;
+        }
 
         if (ret <= 0)
         {
-            BTIF_TRACE_EVENT("uipc_flush_ch_locked : error (%d)", ret);
+            BTIF_TRACE_EVENT("%s() - error (%d). Exiting", __FUNCTION__, ret);
             return;
         }
-        read(pfd.fd, &buf, 1);
+
+        /* read sufficiently large buffer to ensure flush empties socket faster than
+           it is getting refilled */
+        read(pfd.fd, &buf, UIPC_FLUSH_BUFFER_SIZE);
     }
 }