Cross transport key mapping fixes

Change-Id: I22d97303054eccc876c4a9c7c0a50e369ff4fa62
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 1251f5d..64a084d 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -2279,10 +2279,8 @@
                                     bta_dm_search_cb.services_to_search
                                     );
             }
-            if (transport == BT_TRANSPORT_LE)            /*
-            if ( bta_dm_search_cb.p_btm_inq_info != NULL &&
-                 bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE &&
-                 (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK))*/
+
+            if (transport == BT_TRANSPORT_LE)
             {
                 if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK)
                 {
@@ -2730,14 +2728,15 @@
         memcpy(p_auth_cmpl->key, key, LINK_KEY_LEN);
         sec_event.auth_cmpl.fail_reason = HCI_SUCCESS;
 
+        // Report the BR link key based on the BR/EDR address and type
+        BTM_ReadDevInfo(bd_addr, &sec_event.auth_cmpl.dev_type, &sec_event.auth_cmpl.addr_type);
+
         if(bta_dm_cb.p_sec_cback)
-        {
             bta_dm_cb.p_sec_cback(event, &sec_event);
-        }
     }
     else
     {
-        APPL_TRACE_WARNING(" bta_dm_new_link_key_cback() Received AMP Key??  ");
+        APPL_TRACE_WARNING("%s() Received AMP Key", __func__);
     }
 
     return BTM_CMD_STARTED;
@@ -2766,18 +2765,14 @@
         memcpy(sec_event.auth_cmpl.bd_name, bd_name, (BD_NAME_LEN-1));
         sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
 
-/*      taken care of by memset [above]
-        sec_event.auth_cmpl.key_present = FALSE;
-        sec_event.auth_cmpl.success = FALSE;
-*/
+        // Report the BR link key based on the BR/EDR address and type
+        BTM_ReadDevInfo(bd_addr, &sec_event.auth_cmpl.dev_type, &sec_event.auth_cmpl.addr_type);
         sec_event.auth_cmpl.fail_reason = (UINT8)result;
-        if(bta_dm_cb.p_sec_cback)
-        {
-            bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
-        }
-        /* delete this device entry from Sec Dev DB */
-        bta_dm_remove_sec_dev_entry(bd_addr);
 
+        if(bta_dm_cb.p_sec_cback)
+            bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+
+        bta_dm_remove_sec_dev_entry(bd_addr);
     }
 
     return BTM_SUCCESS;
@@ -4390,7 +4385,7 @@
 
         case BTM_LE_COMPLT_EVT:
             bdcpy(sec_event.auth_cmpl.bd_addr, bda);
-            BTM_ReadDevInfo(bda, &dev_type, &sec_event.auth_cmpl.addr_type);
+            BTM_ReadDevInfo(bda, &sec_event.auth_cmpl.dev_type, &sec_event.auth_cmpl.addr_type);
             p_name = BTM_SecReadDevName(bda);
             if (p_name != NULL)
             {
@@ -5417,7 +5412,7 @@
             /* make sure the string is terminated */
             p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
 
-            p_msg->disc_result.result.disc_res.device_type = BT_DEVICE_TYPE_BLE;
+            p_msg->disc_result.result.disc_res.device_type |= BT_DEVICE_TYPE_BLE;
             if ( bta_dm_search_cb.ble_raw_used > 0 )
             {
                 p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.ble_raw_used);
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 9c13be4..ac893e5 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -763,6 +763,7 @@
     UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     tBLE_ADDR_TYPE  addr_type;      /* peer device address type */
+    tBT_DEVICE_TYPE dev_type;
 #endif
 } tBTA_DM_AUTH_CMPL;
 
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
index c4bdf2b..641b60c 100644
--- a/btif/co/bta_dm_co.c
+++ b/btif/co/bta_dm_co.c
@@ -31,15 +31,15 @@
 
 tBTE_APPL_CFG bte_appl_cfg =
 {
-#if SMP_INCLUDED == TRUE && SMP_LE_SC_INCLUDED == TRUE
-    BTA_LE_AUTH_REQ_SC_MITM_BOND, //Authentication requirements
+#if SMP_INCLUDED == TRUE
+    BTA_LE_AUTH_REQ_SC_MITM_BOND, // Authentication requirements
 #else
-    BTM_AUTH_SPGB_YES,  // Authentication requirements
+    BTM_AUTH_SPGB_YES,            // Authentication requirements
 #endif
-    BTM_LOCAL_IO_CAPS_BLE, // I/O capabilities
-    7,                  // Initiaor key size
-    7,                  // Responder key size
-    16                  // Maximum key size
+    BTM_LOCAL_IO_CAPS_BLE,
+    BTM_BLE_INITIATOR_KEY_SIZE,
+    BTM_BLE_RESPONDER_KEY_SIZE,
+    BTM_BLE_MAX_KEY_SIZE
 };
 #endif
 
@@ -426,10 +426,10 @@
     if (bte_appl_cfg.ble_io_cap <=4)
         *p_io_cap = bte_appl_cfg.ble_io_cap;
 
-    if (bte_appl_cfg.ble_init_key<=7)
+    if (bte_appl_cfg.ble_init_key <= BTM_BLE_INITIATOR_KEY_SIZE)
         *p_init_key = bte_appl_cfg.ble_init_key;
 
-    if (bte_appl_cfg.ble_resp_key<=7)
+    if (bte_appl_cfg.ble_resp_key <= BTM_BLE_RESPONDER_KEY_SIZE)
         *p_resp_key = bte_appl_cfg.ble_resp_key;
 
     if (bte_appl_cfg.ble_max_key_size > 7 && bte_appl_cfg.ble_max_key_size <= 16)
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index aed6329..9545b36 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -129,18 +129,19 @@
 {
     bt_bond_state_t state;
     BD_ADDR bd_addr;
-    UINT8   bond_type;
-    UINT8   pin_code_len;
-    UINT8   is_ssp;
-    UINT8   auth_req;
-    UINT8   io_cap;
-    UINT8   autopair_attempts;
-    UINT8   timeout_retries;
-    UINT8   is_local_initiated;
-    UINT8   sdp_attempts;
+    UINT8 bond_type;
+    UINT8 pin_code_len;
+    UINT8 is_ssp;
+    UINT8 auth_req;
+    UINT8 io_cap;
+    UINT8 autopair_attempts;
+    UINT8 timeout_retries;
+    UINT8 is_local_initiated;
+    UINT8 sdp_attempts;
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
-    BOOLEAN          is_le_only;
-    BOOLEAN          is_le_nc;/*LE Numeric comparison*/
+    BOOLEAN is_le_only;
+    BOOLEAN is_le_nc; /* LE Numeric comparison */
+    BD_ADDR static_bdaddr;
     btif_dm_ble_cb_t ble;
 #endif
 } btif_dm_pairing_cb_t;
@@ -203,7 +204,6 @@
 
 static skip_sdp_entry_t sdp_blacklist[] = {{76}}; //Apple Mouse and Keyboard
 
-
 /* This flag will be true if HCI_Inquiry is in progress */
 static BOOLEAN btif_dm_inquiry_in_progress = FALSE;
 
@@ -486,15 +486,20 @@
 
 static void bond_state_changed(bt_status_t status, bt_bdaddr_t *bd_addr, bt_bond_state_t state)
 {
-    /* Send bonding state only once - based on outgoing/incoming we may receive duplicates */
-    if ( (pairing_cb.state == state) && (state == BT_BOND_STATE_BONDING) )
+    // Send bonding state only once - based on outgoing/incoming we may receive duplicates
+    if ((pairing_cb.state == state) && (state == BT_BOND_STATE_BONDING))
+    {
+        // Cross key pairing so send callback for static address
+        if (pairing_cb.static_bdaddr != NULL)
+            HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, bd_addr, state);
         return;
+    }
 
     if (pairing_cb.bond_type == BOND_TYPE_TEMPORARY)
-    {
-       state = BT_BOND_STATE_NONE;
-    }
-    BTIF_TRACE_DEBUG("%s: state=%d prev_state=%d", __FUNCTION__, state, pairing_cb.state);
+        state = BT_BOND_STATE_NONE;
+
+    BTIF_TRACE_DEBUG("%s: state=%d, prev_state=%d, sdp_attempts = %d", __func__,
+                      state, pairing_cb.state, pairing_cb.sdp_attempts);
 
     HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, bd_addr, state);
 
@@ -502,12 +507,12 @@
     {
         pairing_cb.state = state;
         bdcpy(pairing_cb.bd_addr, bd_addr->address);
+    } else {
+        if (!pairing_cb.sdp_attempts)
+            memset(&pairing_cb, 0, sizeof(pairing_cb));
+        else
+            BTIF_TRACE_DEBUG("%s: BR-EDR service discovery active", __func__);
     }
-    else
-    {
-        memset(&pairing_cb, 0, sizeof(pairing_cb));
-    }
-
 }
 
 /* store remote version in bt config to always have access
@@ -531,8 +536,7 @@
 
     if (btm_status == BTM_SUCCESS)
     {
-        /* always update cache to ensure we have availability whenever BTM API
-           is not populated */
+        // Always update cache to ensure we have availability whenever BTM API is not populated
         info.manufacturer = mfct_set;
         info.sub_ver = lmp_subver;
         info.version = lmp_ver;
@@ -591,7 +595,15 @@
     num_properties++;
 
     /* device type */
-    dev_type = device_type;
+    bt_property_t prop_name;
+    uint8_t remote_dev_type;
+    BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_TYPE_OF_DEVICE,
+                                sizeof(uint8_t), &remote_dev_type);
+    if (btif_storage_get_remote_device_property(&bdaddr, &prop_name) == BT_STATUS_SUCCESS)
+         dev_type = remote_dev_type | device_type;
+    else
+         dev_type = device_type;
+
     BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                         BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type);
     status = btif_storage_set_remote_device_property(&bdaddr, &properties[num_properties]);
@@ -663,14 +675,14 @@
     }
     if((btif_config_get_int((char const *)&bdstr,"DevType", &device_type) &&
        (btif_storage_get_remote_addr_type(bd_addr, &addr_type) == BT_STATUS_SUCCESS) &&
-       (device_type == BT_DEVICE_TYPE_BLE)) || (transport == BT_TRANSPORT_LE))
+       (device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) || (transport == BT_TRANSPORT_LE))
     {
-        BTA_DmAddBleDevice(bd_addr->address, addr_type, BT_DEVICE_TYPE_BLE);
+        BTA_DmAddBleDevice(bd_addr->address, addr_type, device_type);
     }
 #endif
 
 #if BLE_INCLUDED == TRUE
-    if(is_hid && device_type != BT_DEVICE_TYPE_BLE)
+    if(is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0)
 #else
     if(is_hid)
 #endif
@@ -708,6 +720,7 @@
     if (btif_hh_virtual_unplug(bd_addr) != BT_STATUS_SUCCESS)
 #endif
     {
+         BTIF_TRACE_DEBUG("%s: Removing HH device", __func__);
          BTA_DmRemoveDevice((UINT8 *)bd_addr->address);
     }
 }
@@ -1039,6 +1052,8 @@
     bt_bond_state_t state = BT_BOND_STATE_NONE;
     BOOLEAN skip_sdp = FALSE;
 
+    BTIF_TRACE_DEBUG("%s: bond state=%d", __func__, pairing_cb.state);
+
     bdcpy(bd_addr.address, p_auth_cmpl->bd_addr);
     if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) )
     {
@@ -1070,6 +1085,9 @@
     // Skip SDP for certain  HID Devices
     if (p_auth_cmpl->success)
     {
+        btif_storage_set_remote_addr_type(&bd_addr, p_auth_cmpl->addr_type);
+        btif_update_remote_properties(p_auth_cmpl->bd_addr,
+                                      p_auth_cmpl->bd_name, NULL, p_auth_cmpl->dev_type);
         pairing_cb.timeout_retries = 0;
         status = BT_STATUS_SUCCESS;
         state = BT_BOND_STATE_BONDED;
@@ -1104,17 +1122,25 @@
         {
             /* Trigger SDP on the device */
             pairing_cb.sdp_attempts = 1;;
+            /* If bonded due to cross-key, save the static address too*/
+            if(pairing_cb.state == BT_BOND_STATE_BONDING &&
+              (bdcmp(p_auth_cmpl->bd_addr, pairing_cb.bd_addr) != 0))
+            {
+                BTIF_TRACE_DEBUG("%s: bonding initiated due to cross key, adding static address",
+                                 __func__);
+                bdcpy(pairing_cb.static_bdaddr, p_auth_cmpl->bd_addr);
+            }
 
             if(btif_dm_inquiry_in_progress)
                 btif_dm_cancel_discovery();
 
             btif_dm_get_remote_services(&bd_addr);
-            }
-            /* Do not call bond_state_changed_cb yet. Wait till fetch remote service is complete */
+        }
+        // Do not call bond_state_changed_cb yet. Wait until remote service discovery is complete
     }
     else
     {
-         /*Map the HCI fail reason  to  bt status  */
+        // Map the HCI fail reason  to  bt status
         switch(p_auth_cmpl->fail_reason)
         {
             case HCI_ERR_PAGE_TIMEOUT:
@@ -1428,16 +1454,23 @@
             ** bond_state_changed needs to be sent prior to remote_device_property
             */
             if ((pairing_cb.state == BT_BOND_STATE_BONDING) &&
-                (bdcmp(p_data->disc_res.bd_addr, pairing_cb.bd_addr) == 0)&&
-                pairing_cb.sdp_attempts > 0)
+                ((bdcmp(p_data->disc_res.bd_addr, pairing_cb.bd_addr) == 0) ||
+                 (bdcmp(p_data->disc_res.bd_addr, pairing_cb.static_bdaddr) == 0)) &&
+                  pairing_cb.sdp_attempts > 0)
             {
                  BTIF_TRACE_DEBUG("%s Remote Service SDP done. Call bond_state_changed_cb BONDED",
                                    __FUNCTION__);
                  pairing_cb.sdp_attempts  = 0;
+
+                 // If bonding occured due to cross-key pairing, send bonding callback
+                 // for static address now
+                 if (bdcmp(p_data->disc_res.bd_addr, pairing_cb.static_bdaddr) == 0)
+                    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+
                  bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDED);
             }
 
-            if(p_data->disc_res.num_uuids != 0)
+            if (p_data->disc_res.num_uuids != 0)
             {
                 /* Also write this to the NVRAM */
                 ret = btif_storage_set_remote_device_property(&bd_addr, &prop);
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index bb640f0..b532937 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -27,6 +27,7 @@
  *
  *
  */
+#include <assert.h>
 #include <stdlib.h>
 #include <time.h>
 #include <string.h>
@@ -215,6 +216,7 @@
     } while (*p_start != 0);
     *p_num_uuid = num;
 }
+
 static int prop2cfg(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop)
 {
     bdstr_t bdstr = {0};
@@ -307,6 +309,7 @@
     }
     return TRUE;
 }
+
 static int cfg2prop(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop)
 {
     bdstr_t bdstr = {0};
@@ -542,19 +545,44 @@
     return BT_STATUS_SUCCESS;
 }
 
-/************************************************************************************
-**  Externs
-************************************************************************************/
+static void btif_read_le_key(const uint8_t key_type, const size_t key_len, bt_bdaddr_t bd_addr,
+                 const uint8_t addr_type, const bool add_key, bool *device_added, bool *key_found)
+{
+    assert(device_added);
+    assert(key_found);
 
-/************************************************************************************
-**  Functions
-************************************************************************************/
+    char buffer[100];
+    memset(buffer, 0, sizeof(buffer));
 
-/** functions are synchronous.
- * functions can be called by both internal modules such as BTIF_DM and by external entiries from HAL via BTIF_context_switch
- * For OUT parameters,  caller is expected to provide the memory.
- * Caller is expected to provide a valid pointer to 'property->value' based on the property->type
- */
+    if (btif_storage_get_ble_bonding_key(&bd_addr, key_type, buffer, key_len) == BT_STATUS_SUCCESS)
+    {
+        if (add_key)
+        {
+            BD_ADDR bta_bd_addr;
+            bdcpy(bta_bd_addr, bd_addr.address);
+
+            if (!device_added)
+            {
+                BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                *device_added = true;
+            }
+            BTA_DmAddBleKey(bta_bd_addr, (tBTA_LE_KEY_VALUE *)buffer, key_type);
+        }
+
+        *key_found = true;
+    }
+}
+
+/*******************************************************************************
+ * Functions
+ *
+ * Functions are synchronous and can be called by both from internal modules
+ * such as BTIF_DM and by external entiries from HAL via BTIF_context_switch.
+ * For OUT parameters, the caller is expected to provide the memory.
+ * Caller is expected to provide a valid pointer to 'property->value' based on
+ * the property->type.
+ *******************************************************************************/
+
 /*******************************************************************************
 **
 ** Function         btif_storage_get_adapter_property
@@ -1153,197 +1181,59 @@
     return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
-bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr,int add, btif_bonded_devices_t *p_bonded_devices)
+bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add, btif_bonded_devices_t *p_bonded_devices)
 {
     int device_type;
     int addr_type;
-    char buf[100];
     UINT32 i;
     bt_bdaddr_t bd_addr;
     BD_ADDR bta_bd_addr;
-    BOOLEAN is_device_added =FALSE;
-    BOOLEAN key_found = FALSE;
-    tBTA_LE_KEY_VALUE *p;
+    bool device_added = false;
+    bool key_found = false;
 
-    if(!btif_config_get_int(remote_bd_addr,"DevType", &device_type))
+    if (!btif_config_get_int(remote_bd_addr, "DevType", &device_type))
         return BT_STATUS_FAIL;
-    if(device_type == BT_DEVICE_TYPE_BLE)
+
+    if ((device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE)
     {
-            BTIF_TRACE_DEBUG("%s %s found a BLE device", __FUNCTION__,remote_bd_addr);
-            string_to_bdaddr(remote_bd_addr, &bd_addr);
-            bdcpy(bta_bd_addr, bd_addr.address);
-            if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS)
-            {
-                return BT_STATUS_FAIL;
-            }
+        BTIF_TRACE_DEBUG("%s Found a LE device: %s", __func__, remote_bd_addr);
 
-            memset(buf, 0, sizeof(buf));
-            if (btif_storage_get_ble_bonding_key(&bd_addr,
-                                                 BTIF_DM_LE_KEY_PENC,
-                                                 buf,
-                                                 sizeof(btif_dm_ble_penc_keys_t)) == BT_STATUS_SUCCESS)
-            {
-                if(add)
-                {
-                    if (!is_device_added)
-                    {
-                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
-                        is_device_added = TRUE;
-                    }
-                    p = (tBTA_LE_KEY_VALUE *)buf;
-                    for (i=0; i<16; i++)
-                    {
-                        BTIF_TRACE_DEBUG("penc_key.ltk[%d]=0x%02x",i,p->penc_key.ltk[i]);
-                    }
-                    for (i=0; i<8; i++)
-                    {
-                        BTIF_TRACE_DEBUG("penc_key.rand[%d]=0x%02x",i,p->penc_key.rand[i]);
-                    }
-                    BTIF_TRACE_DEBUG("p->penc_key.ediv=0x%04x",p->penc_key.ediv);
-                    BTIF_TRACE_DEBUG("p->penc_key.sec_level=0x%02x",p->penc_key.sec_level);
-                    BTIF_TRACE_DEBUG("p->penc_key.key_size=0x%02x",p->penc_key.key_size);
-                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PENC);
-                }
-                key_found = TRUE;
-            }
+        string_to_bdaddr(remote_bd_addr, &bd_addr);
+        bdcpy(bta_bd_addr, bd_addr.address);
 
-            memset(buf, 0, sizeof(buf));
-            if (btif_storage_get_ble_bonding_key(&bd_addr,
-                                                 BTIF_DM_LE_KEY_PID,
-                                                 buf,
-                                                 sizeof(btif_dm_ble_pid_keys_t)) == BT_STATUS_SUCCESS)
-            {
-                if(add)
-                {
-                    if (!is_device_added)
-                    {
-                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
-                        is_device_added = TRUE;
-                    }
-                    p = (tBTA_LE_KEY_VALUE *)buf;
-                    for (i=0; i<16; 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]);
-                    }
+        if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS)
+        {
+            addr_type = BLE_ADDR_PUBLIC;
+            btif_storage_set_remote_addr_type(&bd_addr, BLE_ADDR_PUBLIC);
+        }
 
-                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PID);
-                }
-                key_found = TRUE;
-            }
+        btif_read_le_key(BTIF_DM_LE_KEY_PENC, sizeof(btif_dm_ble_penc_keys_t),
+                         bd_addr, addr_type, add, &device_added, &key_found);
 
-            if (btif_storage_get_ble_bonding_key(&bd_addr, BTIF_DM_LE_KEY_LID, buf,
-                                    sizeof(btif_dm_ble_pid_keys_t))== BT_STATUS_SUCCESS)
-            {
-                if(add)
-                {
-                    if (!is_device_added)
-                    {
-                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
-                        is_device_added = TRUE;
-                    }
-                    p = (tBTA_LE_KEY_VALUE *)buf;
-                    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]);
-                    }
+        btif_read_le_key(BTIF_DM_LE_KEY_PID, sizeof(btif_dm_ble_pid_keys_t),
+                         bd_addr, addr_type, add, &device_added, &key_found);
 
-                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LID);
-                }
-                key_found = TRUE;
-            }
+        btif_read_le_key(BTIF_DM_LE_KEY_LID, sizeof(btif_dm_ble_pid_keys_t),
+                         bd_addr, addr_type, add, &device_added, &key_found);
 
-            memset(buf, 0, sizeof(buf));
-            if (btif_storage_get_ble_bonding_key(&bd_addr,
-                                                 BTIF_DM_LE_KEY_PCSRK,
-                                                 buf,
-                                                 sizeof(btif_dm_ble_pcsrk_keys_t)) == BT_STATUS_SUCCESS)
-            {
-                if(add)
-                {
-                    if (!is_device_added)
-                    {
-                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
-                        is_device_added = TRUE;
-                    }
+        btif_read_le_key(BTIF_DM_LE_KEY_PCSRK, sizeof(btif_dm_ble_pcsrk_keys_t),
+                         bd_addr, addr_type, add, &device_added, &key_found);
 
-                    p = (tBTA_LE_KEY_VALUE *)buf;
-                    for (i=0; i<16; i++)
-                    {
-                        BTIF_TRACE_DEBUG("p->pcsrk_key.csrk[%d]=0x%02x",i, p->psrk_key.csrk[i]);
-                    }
-                    BTIF_TRACE_DEBUG("p->pcsrk_key.counter=0x%08x",p->psrk_key.counter);
-                    BTIF_TRACE_DEBUG("p->pcsrk_key.sec_level=0x%02x",p->psrk_key.sec_level);
+        btif_read_le_key(BTIF_DM_LE_KEY_LENC, sizeof(btif_dm_ble_lenc_keys_t),
+                         bd_addr, addr_type, add, &device_added, &key_found);
 
-                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PCSRK);
-                }
-                key_found = TRUE;
-            }
+        btif_read_le_key(BTIF_DM_LE_KEY_LCSRK, sizeof(btif_dm_ble_lcsrk_keys_t),
+                         bd_addr, addr_type, add, &device_added, &key_found);
 
-            memset(buf, 0, sizeof(buf));
-            if (btif_storage_get_ble_bonding_key(&bd_addr,
-                                                 BTIF_DM_LE_KEY_LENC,
-                                                 buf,
-                                                 sizeof(btif_dm_ble_lenc_keys_t)) == BT_STATUS_SUCCESS)
-            {
-                if(add)
-                {
-                    if (!is_device_added)
-                    {
-                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
-                        is_device_added = TRUE;
-                    }
-                    p = (tBTA_LE_KEY_VALUE *)buf;
-                    BTIF_TRACE_DEBUG("p->lenc_key.div=0x%04x",p->lenc_key.div);
-                    BTIF_TRACE_DEBUG("p->lenc_key.key_size=0x%02x",p->lenc_key.key_size);
-                    BTIF_TRACE_DEBUG("p->lenc_key.sec_level=0x%02x",p->lenc_key.sec_level);
+        // Fill in the bonded devices
+        if (device_added)
+        {
+            memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t));
+            btif_gatts_add_bonded_dev_from_nv(bta_bd_addr);
+        }
 
-                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LENC);
-                }
-                key_found = TRUE;
-            }
-
-            memset(buf, 0, sizeof(buf));
-            if (btif_storage_get_ble_bonding_key(&bd_addr,
-                                                 BTIF_DM_LE_KEY_LCSRK,
-                                                 buf,
-                                                 sizeof(btif_dm_ble_lcsrk_keys_t)) == BT_STATUS_SUCCESS)
-            {
-                if(add)
-                {
-                    if (!is_device_added)
-                    {
-                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
-                        is_device_added = TRUE;
-                    }
-                    p = (tBTA_LE_KEY_VALUE *)buf;
-                    BTIF_TRACE_DEBUG("p->lcsrk_key.div=0x%04x",p->lcsrk_key.div);
-                    BTIF_TRACE_DEBUG("p->lcsrk_key.counter=0x%08x",p->lcsrk_key.counter);
-                    BTIF_TRACE_DEBUG("p->lcsrk_key.sec_level=0x%02x",p->lcsrk_key.sec_level);
-
-                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LCSRK);
-                }
-                key_found = TRUE;
-            }
-
-            /* Fill in the bonded devices */
-            if (is_device_added)
-            {
-                memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t));
-                btif_gatts_add_bonded_dev_from_nv(bta_bd_addr);
-            }
-
-            if(key_found)
-                return BT_STATUS_SUCCESS;
-            else
-                return BT_STATUS_FAIL;
+        if (key_found)
+            return BT_STATUS_SUCCESS;
     }
     return BT_STATUS_FAIL;
 }
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index c72ed3f..8201c57 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -125,11 +125,10 @@
         BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
                        (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
     }
-    p_dev_rec->device_type = dev_type;
+    p_dev_rec->device_type |= dev_type;
     p_dev_rec->ble.ble_addr_type = addr_type;
-    BTM_TRACE_DEBUG ("p_dev_rec->device_type =0x%x  addr_type=0x%x sec_flags=0x%x",
-                      dev_type,  addr_type, p_dev_rec->sec_flags);
 
+    memcpy (p_dev_rec->ble.pseudo_addr, bd_addr, BD_ADDR_LEN);
     /* sync up with the Inq Data base*/
     p_info = BTM_InqDbRead(bd_addr);
     if (p_info)
@@ -1395,7 +1394,7 @@
 
     }
     /* to notify GATT to send data if any request is pending */
-    gatt_notify_enc_cmpl(p_dev_rec->bd_addr);
+    gatt_notify_enc_cmpl(p_dev_rec->ble.pseudo_addr);
 }
 
 /*******************************************************************************
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 142b8d8..b3a3b33 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -262,6 +262,74 @@
     }
     return FALSE;
 }
+
+/*******************************************************************************
+**
+** Function         btm_ble_init_pseudo_addr
+**
+** Description      This function is used to initialize pseudo address.
+**                  If pseudo address is not available, use dummy address
+**
+** Returns          TRUE is updated; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_init_pseudo_addr (tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR new_pseudo_addr)
+{
+    BD_ADDR dummy_bda = {0};
+
+    if (memcmp(p_dev_rec->ble.pseudo_addr, dummy_bda, BD_ADDR_LEN) == 0)
+    {
+        memcpy(p_dev_rec->ble.pseudo_addr, new_pseudo_addr, BD_ADDR_LEN);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_addr_resolvable
+**
+** Description      This function checks if a RPA is resolvable by the device key.
+**
+** Returns          TRUE is resolvable; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_addr_resolvable (BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    BOOLEAN rt = FALSE;
+
+    if (!BTM_BLE_IS_RESOLVE_BDA(rpa))
+        return rt;
+
+    UINT8 rand[3];
+    tSMP_ENC output;
+    if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
+        (p_dev_rec->ble.key_type & BTM_LE_KEY_PID))
+    {
+        BTM_TRACE_DEBUG("%s try to resolve", __func__);
+        /* use the 3 MSB of bd address as prand */
+        rand[0] = rpa[2];
+        rand[1] = rpa[1];
+        rand[2] = rpa[0];
+
+        /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
+        SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN,
+                    &rand[0], 3, &output);
+
+        rand[0] = rpa[5];
+        rand[1] = rpa[4];
+        rand[2] = rpa[3];
+
+        if (!memcmp(output.param_buf, &rand[0], 3))
+        {
+            btm_ble_init_pseudo_addr (p_dev_rec, rpa);
+            rt = TRUE;
+        }
+    }
+    return rt;
+}
+
 /*******************************************************************************
 **
 ** Function         btm_ble_match_random_bda
@@ -276,23 +344,24 @@
 static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index)
 {
 #if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
-    tBTM_SEC_DEV_REC    *p_dev_rec;
-    tBTM_LE_RANDOM_CB   *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
-    UINT8       rand[3];
-    tSMP_ENC    output;
-
     /* use the 3 MSB of bd address as prand */
+
+    tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+    UINT8 rand[3];
     rand[0] = p_mgnt_cb->random_bda[2];
     rand[1] = p_mgnt_cb->random_bda[1];
     rand[2] = p_mgnt_cb->random_bda[0];
 
-    BTM_TRACE_EVENT("btm_ble_match_random_bda rec_index = %d", rec_index);
+    BTM_TRACE_EVENT("%s rec_index = %d", __func__, rec_index);
 
     if (rec_index < BTM_SEC_MAX_DEVICE_RECORDS)
     {
+        tSMP_ENC output;
+        tBTM_SEC_DEV_REC *p_dev_rec;
         p_dev_rec = &btm_cb.sec_dev_rec[rec_index];
 
-        BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags, p_dev_rec->device_type);
+        BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags,
+                        p_dev_rec->device_type);
 
         if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
             (p_dev_rec->ble.key_type & BTM_LE_KEY_PID))
@@ -370,7 +439,7 @@
     tBTM_SEC_DEV_REC    *p_dev_rec = NULL;
     BTM_TRACE_EVENT ("btm_ble_map_bda_to_conn_bda");
     if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL &&
-        p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+        (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE)
     {
         if (p_dev_rec->ble.ble_addr_type != BLE_ADDR_PUBLIC)
         {
@@ -439,8 +508,12 @@
 
         /* assign the original address to be the current report address */
         memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
-        *p_addr_type = p_dev_rec->ble.ble_addr_type;
 
+        /* assign the original address to be the current report address */
+        if (!btm_ble_init_pseudo_addr (p_dev_rec, bd_addr))
+            memcpy(bd_addr, p_dev_rec->ble.pseudo_addr, BD_ADDR_LEN);
+
+        *p_addr_type = p_dev_rec->ble.ble_addr_type;
         return TRUE;
     }
 #endif
@@ -487,8 +560,8 @@
                                                   UINT8 rra_type)
 {
 #if BLE_PRIVACY_SPT == TRUE
-    UINT8               rra_dummy = FALSE;
-    BD_ADDR             dummy_bda = {0};
+    UINT8 rra_dummy = FALSE;
+    BD_ADDR dummy_bda = {0};
 
     if (memcmp(dummy_bda, rpa, BD_ADDR_LEN) == 0)
         rra_dummy = TRUE;
@@ -515,7 +588,10 @@
                     __func__, p_sec_rec->ble.active_addr_type);
 
     /* connection refresh remote address */
-    tACL_CONN *p_acl = p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+    tACL_CONN *p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+    if (p_acl == NULL)
+        p_acl = btm_bda_to_acl(p_sec_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
+
     if (p_acl != NULL)
     {
         if (rra_type == BTM_BLE_ADDR_PSEUDO)
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 46953db..8912c25 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -2654,8 +2654,10 @@
     {
         /* new device */
         if (p_i == NULL ||
-            (/* assume a DUMO device, BR/EDR inquiry is always active */
-             p_i && p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BLE && p_i->scan_rsp))
+            /* assume a DUMO device, BR/EDR inquiry is always active */
+            (p_i &&
+            (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE &&
+             p_i->scan_rsp))
         {
             BTM_TRACE_WARNING("INQ RES: Extra Response Received...cancelling inquiry..");
 
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 9d5c493..adf0837 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -290,42 +290,43 @@
     /*****************************************************
     **      BLE Inquiry
     *****************************************************/
-    tBTM_BLE_INQ_CB     inq_var;
+    tBTM_BLE_INQ_CB inq_var;
 
     /* observer callback and timer */
     tBTM_INQ_RESULTS_CB *p_obs_results_cb;
-    tBTM_CMPL_CB        *p_obs_cmpl_cb;
-    TIMER_LIST_ENT      obs_timer_ent;
+    tBTM_CMPL_CB *p_obs_cmpl_cb;
+    TIMER_LIST_ENT obs_timer_ent;
 
     /* background connection procedure cb value */
-    tBTM_BLE_CONN_TYPE  bg_conn_type;
-    UINT16              scan_int;
-    UINT16              scan_win;
-    tBTM_BLE_SEL_CBACK  *p_select_cback;
+    tBTM_BLE_CONN_TYPE bg_conn_type;
+    UINT16 scan_int;
+    UINT16 scan_win;
+    tBTM_BLE_SEL_CBACK *p_select_cback;
 
     /* white list information */
     UINT8                   white_list_avail_size;
     tBTM_BLE_WL_STATE       wl_state;
 
-    BUFFER_Q                conn_pending_q;
-    tBTM_BLE_CONN_ST        conn_state;
+    BUFFER_Q conn_pending_q;
+    tBTM_BLE_CONN_ST conn_state;
 
     /* random address management control block */
-    tBTM_LE_RANDOM_CB   addr_mgnt_cb;
+    tBTM_LE_RANDOM_CB addr_mgnt_cb;
 
-    BOOLEAN          enabled;
+    BOOLEAN enabled;
 
 #if BLE_PRIVACY_SPT == TRUE
-    BOOLEAN             mixed_mode; /* privacy 1.2 mixed mode is on or not */
-    tBTM_PRIVACY_MODE   privacy_mode;               /* privacy mode */
-    UINT8               resolving_list_avail_size;     /* resolving list available size */
-    tBTM_BLE_RESOLVE_Q   resolving_list_pend_q;
+    BOOLEAN mixed_mode; /* privacy 1.2 mixed mode is on or not */
+    tBTM_PRIVACY_MODE privacy_mode;               /* privacy mode */
+    UINT8 resolving_list_avail_size;     /* resolving list available size */
+    UINT8 *irk_list_mask;     /* IRK list availability mask, up to max entry bits */
+    tBTM_BLE_RESOLVE_Q resolving_list_pend_q;
 #endif
-    tBTM_BLE_WL_OP  wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
+    tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
 
     /* current BLE link state */
-    tBTM_BLE_STATE_MASK           cur_states;  /* bit mask of tBTM_BLE_STATE */
-    UINT8  link_count[2];    /* total link count master and slave*/
+    tBTM_BLE_STATE_MASK cur_states;  /* bit mask of tBTM_BLE_STATE */
+    UINT8 link_count[2];    /* total link count master and slave*/
 } tBTM_BLE_CB;
 
 #ifdef __cplusplus
diff --git a/stack/btm/btm_ble_privacy.c b/stack/btm/btm_ble_privacy.c
index b905eac..9174116 100644
--- a/stack/btm/btm_ble_privacy.c
+++ b/stack/btm/btm_ble_privacy.c
@@ -62,13 +62,12 @@
 ** Returns          void
 **
 *******************************************************************************/
-void btm_ble_enq_resolving_list_pending(BD_ADDR psuedo_bda, UINT8 op_code)
+void btm_ble_enq_resolving_list_pending(BD_ADDR pseudo_bda, UINT8 op_code)
 {
-    tBTM_BLE_RESOLVE_Q          *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+    tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
 
-    memcpy(p_q->resolve_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
+    memcpy(p_q->resolve_q_random_pseudo[p_q->q_next], pseudo_bda, BD_ADDR_LEN);
     p_q->resolve_q_action[p_q->q_next] = op_code;
-
     p_q->q_next ++;
     p_q->q_next %= controller_get_interface()->get_ble_resolving_list_max_size();
 }
@@ -85,13 +84,13 @@
 ** Returns          void
 **
 *******************************************************************************/
-BOOLEAN btm_ble_brcm_find_resolving_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
+BOOLEAN btm_ble_brcm_find_resolving_pending_entry(BD_ADDR pseudo_addr, UINT8 action)
 {
     tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
 
-    for (UINT8 i = p_q->q_pending; i != p_q->q_next; )
+    for (UINT8 i = p_q->q_pending; i != p_q->q_next;)
     {
-        if (memcmp(p_q->resolve_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
+        if (memcmp(p_q->resolve_q_random_pseudo[i], pseudo_addr, BD_ADDR_LEN) == 0 &&
             action == p_q->resolve_q_action[i])
             return TRUE;
 
@@ -107,52 +106,83 @@
 **
 ** Description      dequeue target address from resolving pending operation queue
 **
-** Parameters       psuedo_addr: psuedo_addr device address
+** Parameters       pseudo_addr: pseudo_addr device address
 **
 ** Returns          void
 **
 *******************************************************************************/
-BOOLEAN btm_ble_deq_resolving_pending(BD_ADDR psuedo_addr)
+BOOLEAN btm_ble_deq_resolving_pending(BD_ADDR pseudo_addr)
 {
     tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
 
     if (p_q->q_next != p_q->q_pending)
     {
-        memcpy(psuedo_addr, p_q->resolve_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
+        memcpy(pseudo_addr, p_q->resolve_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
         memset(p_q->resolve_q_random_pseudo[p_q->q_pending], 0, BD_ADDR_LEN);
-
         p_q->q_pending ++;
         p_q->q_pending %= controller_get_interface()->get_ble_resolving_list_max_size();
-
         return TRUE;
     }
+
     return FALSE;
 }
 
 /*******************************************************************************
 **
-** Function         btm_ble_find_resolving_list_entry
+** Function         btm_ble_clear_irk_index
 **
-** Description      find the device record if the pseudo address is currently in
-**                  the resolving list
+** Description      clear IRK list index mask for availability
 **
-** Returns          pointer to the security device record; NULL otherwise
+** Returns          none
 **
 *******************************************************************************/
-tBTM_SEC_DEV_REC * btm_ble_find_resolving_list_entry(BD_ADDR pseudo_bda)
+void btm_ble_clear_irk_index(UINT8 index)
 {
-    tBTM_SEC_DEV_REC  *p_dev_rec = &btm_cb.sec_dev_rec[0];
+    tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+    UINT8 byte;
+    UINT8 bit;
 
     for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec++)
     {
-        if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
-            (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
-            memcmp(p_dev_rec->bd_addr, pseudo_bda, BD_ADDR_LEN) == 0)
+        if (index < controller_get_interface()->get_ble_resolving_list_max_size())
         {
-            return p_dev_rec ;
+            byte = index / 8;
+            bit = index % 8;
+            btm_cb.ble_ctr_cb.irk_list_mask[byte] &= (~(1 << bit));
         }
     }
-    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_find_irk_index
+**
+** Description      find the first available IRK list index
+**
+** Returns          index from 0 ~ max (127 default)
+**
+*******************************************************************************/
+UINT8 btm_ble_find_irk_index(void)
+{
+    UINT8 i = 0;
+    UINT8 byte;
+    UINT8 bit;
+
+    while (i < controller_get_interface()->get_ble_resolving_list_max_size())
+    {
+        byte = i / 8;
+        bit = i % 8;
+
+        if ((btm_cb.ble_ctr_cb.irk_list_mask[byte] & (1 << bit)) == 0)
+        {
+            btm_cb.ble_ctr_cb.irk_list_mask[byte] |= (1 << bit);
+            return i;
+        }
+        i++;
+    }
+
+    BTM_TRACE_ERROR ("%s failed, list full", __func__);
+    return i;
 }
 
 /*******************************************************************************
@@ -166,21 +196,25 @@
 *******************************************************************************/
 void btm_ble_update_resolving_list(BD_ADDR pseudo_bda, BOOLEAN add)
 {
-    tBTM_SEC_DEV_REC   *p_dev_rec = btm_find_dev (pseudo_bda);
-
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_bda);
     if (p_dev_rec == NULL)
         return;
 
     if (add)
     {
         p_dev_rec->ble.in_controller_list |= BTM_RESOLVING_LIST_BIT;
-        /* set resolving list entry index : = max- available - 1*/
-        p_dev_rec->ble.resolving_list_index =
-            controller_get_interface()->get_ble_resolving_list_max_size() -
-                                btm_cb.ble_ctr_cb.resolving_list_avail_size - 1;
-    } else {
+        if (!controller_get_interface()->supports_ble_privacy())
+            p_dev_rec->ble.resolving_list_index = btm_ble_find_irk_index();
+    }
+    else
+    {
         p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
-        p_dev_rec->ble.resolving_list_index = 0;
+        if (!controller_get_interface()->supports_ble_privacy())
+        {
+           /* clear IRK list index mask */
+           btm_ble_clear_irk_index(p_dev_rec->ble.resolving_list_index);
+           p_dev_rec->ble.resolving_list_index = 0;
+        }
     }
 }
 
@@ -196,31 +230,37 @@
 *******************************************************************************/
 void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len)
 {
-    UINT8 status;
+    UINT8 status = 0;
     STREAM_TO_UINT8(status, p);
 
-    BTM_TRACE_DEBUG("%s status = %d", __func__, status);
-
-    /* standard HCI status only have one status byte, if greater than 3, VSC complete received */
-    if (evt_len >= 3)
-    {
-        /* VSC complete has one extra byte for op code and list size, skip it here */
-        p ++;
-        /* updated the available list size, and current list size */
-        UINT8 max_resolving_list_size;
-        STREAM_TO_UINT8(max_resolving_list_size, p);
-        controller_get_interface()->set_ble_resolving_list_max_size(max_resolving_list_size);
-    }
+    BTM_TRACE_DEBUG("%s status=%d", __func__, status);
 
     if (status == HCI_SUCCESS)
     {
-        btm_cb.ble_ctr_cb.resolving_list_avail_size  =
+        if (evt_len >= 3)
+        {
+            /* VSC complete has one extra byte for op code and list size, skip it here */
+            p ++;
+
+            /* updated the available list size, and current list size */
+            uint8_t irk_list_sz_max = 0;
+            STREAM_TO_UINT8(irk_list_sz_max, p);
+
+            if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+                btm_ble_resolving_list_init(irk_list_sz_max);
+
+            uint8_t irk_mask_size = (irk_list_sz_max % 8) ?
+                            (irk_list_sz_max / 8 + 1) : (irk_list_sz_max / 8);
+            memset(btm_cb.ble_ctr_cb.irk_list_mask, 0, irk_mask_size);
+        }
+
+        btm_cb.ble_ctr_cb.resolving_list_avail_size =
             controller_get_interface()->get_ble_resolving_list_max_size();
 
-        BTM_TRACE_DEBUG("%s resolving_list_avail_size = %d",
+        BTM_TRACE_DEBUG("%s resolving_list_avail_size=%d",
                         __func__, btm_cb.ble_ctr_cb.resolving_list_avail_size);
 
-        for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++)
+        for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; ++i)
             btm_cb.sec_dev_rec[i].ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
     }
 }
@@ -237,13 +277,13 @@
 *******************************************************************************/
 void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
 {
-    UINT8           status;
+    UINT8 status;
     STREAM_TO_UINT8(status, p);
 
     BTM_TRACE_DEBUG("%s status = %d", __func__, status);
 
     BD_ADDR pseudo_bda;
-    if (!btm_ble_deq_resolving_pending( pseudo_bda))
+    if (!btm_ble_deq_resolving_pending(pseudo_bda))
     {
         BTM_TRACE_DEBUG("no pending resolving list operation");
         return;
@@ -260,7 +300,6 @@
         }
         else
             btm_cb.ble_ctr_cb.resolving_list_avail_size --;
-
     }
     else if (status == HCI_ERR_MEMORY_FULL) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED  */
     {
@@ -281,10 +320,10 @@
 *******************************************************************************/
 void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
 {
-    BD_ADDR         pseudo_bda;
+    BD_ADDR pseudo_bda;
+    UINT8 status;
 
-    UINT8           status;
-    STREAM_TO_UINT8  (status, p);
+    STREAM_TO_UINT8(status, p);
 
     BTM_TRACE_DEBUG("%s status = %d", __func__, status);
 
@@ -299,14 +338,14 @@
         /* proprietary: spec does not have these extra bytes */
         if (evt_len > 2)
         {
-            p ++;  /* skip opcode */
+            p ++; /* skip opcode */
             STREAM_TO_UINT8(btm_cb.ble_ctr_cb.resolving_list_avail_size, p);
         }
         else
-            btm_cb.ble_ctr_cb.resolving_list_avail_size ++;
-
+            btm_cb.ble_ctr_cb.resolving_list_avail_size++;
     }
 }
+
 /*******************************************************************************
 **
 ** Function         btm_ble_read_resolving_list_entry_complete
@@ -409,14 +448,19 @@
 *******************************************************************************/
 tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec)
 {
-    tBTM_STATUS st = BTM_NO_RESOURCES;
+    /* if controller does not support RPA offloading or privacy 1.2, skip */
+    if (controller_get_interface()->get_ble_resolving_list_max_size())
+        return BTM_WRONG_MODE;
 
+    tBTM_STATUS st = BTM_NO_RESOURCES;
     if (controller_get_interface()->supports_ble_privacy())
     {
-        if (btsnd_hcic_ble_rm_device_resolving_list (p_dev_rec->ble.static_addr_type,
-                                                 p_dev_rec->ble.static_addr))
+        if (btsnd_hcic_ble_rm_device_resolving_list(p_dev_rec->ble.static_addr_type,
+                                                    p_dev_rec->ble.static_addr))
             st =  BTM_CMD_STARTED;
-    } else {
+    }
+    else
+    {
         UINT8 param[20]= {0};
         UINT8 *p = param;
 
@@ -424,16 +468,14 @@
         UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
         BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
 
-        st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
-                                        BTM_BLE_META_REMOVE_IRK_LEN,
-                                        param,
-                                        btm_ble_resolving_list_vsc_op_cmpl);
+        st = BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC,
+                                       BTM_BLE_META_REMOVE_IRK_LEN,
+                                       param,
+                                       btm_ble_resolving_list_vsc_op_cmpl);
     }
 
     if (st == BTM_CMD_STARTED)
-    {
         btm_ble_enq_resolving_list_pending( p_dev_rec->bd_addr, BTM_BLE_META_REMOVE_IRK_ENTRY);
-    }
 
     return st;
 }
@@ -494,8 +536,8 @@
     if (controller_get_interface()->supports_ble_privacy())
     {
         if (btsnd_hcic_ble_read_resolvable_addr_peer(p_dev_rec->ble.static_addr_type,
-                                                 p_dev_rec->ble.static_addr))
-             st =  BTM_CMD_STARTED;
+                                                     p_dev_rec->ble.static_addr))
+            st =  BTM_CMD_STARTED;
     }
     else
     {
@@ -512,9 +554,8 @@
     }
 
     if (st == BTM_CMD_STARTED)
-    {
-        btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr, BTM_BLE_META_READ_IRK_ENTRY);
-    }
+        btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+                                           BTM_BLE_META_READ_IRK_ENTRY);
 
     return st;
 }
@@ -532,28 +573,31 @@
 *******************************************************************************/
 BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
 {
-    BOOLEAN         rt = FALSE;
-    tBTM_BLE_CB     *p_cb = &btm_cb.ble_ctr_cb;
-
+    BOOLEAN rt = FALSE;
     BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
-                    btm_cb.ble_ctr_cb.privacy_mode);
+                                btm_cb.ble_ctr_cb.privacy_mode);
 
+    /* if controller does not support RPA offloading or privacy 1.2, skip */
+    if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+        return FALSE;
+
+    BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d",
+                    __func__, btm_cb.ble_ctr_cb.privacy_mode);
+
+    /* only add RPA enabled device into resolving list */
     if (p_dev_rec != NULL && /* RPA is being used and PID is known */
         p_dev_rec->sec_flags & BTM_SEC_IN_USE &&
-        /* only add RPA enabled device into resolving list */
-        (((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0
-          && BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
-       || ((p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0
-          && btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)))
+        ((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0 ||
+        ((p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0 &&
+          btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)))
     {
         if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
             btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
                                                       BTM_BLE_META_ADD_IRK_ENTRY) == FALSE)
         {
-            if (p_cb->resolving_list_avail_size > 0)
+            if (btm_cb.ble_ctr_cb.resolving_list_avail_size > 0)
             {
-                btm_ble_update_resolving_list( p_dev_rec->bd_addr, TRUE);
-
+                btm_ble_update_resolving_list(p_dev_rec->bd_addr, TRUE);
                 if (controller_get_interface()->supports_ble_privacy())
                 {
                     UINT8 dummy_irk[HCIC_BLE_IRK_SIZE];
@@ -561,9 +605,9 @@
 
                     UINT8 *peer_irk;
                     if (BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
-                        peer_irk = p_dev_rec->ble.keys.irk;
+                         peer_irk = p_dev_rec->ble.keys.irk;
                     else
-                        peer_irk = dummy_irk;
+                         peer_irk = dummy_irk;
 
                     UINT8 *local_irk;
                     if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
@@ -573,17 +617,29 @@
 
                     BD_ADDR dummy_bda = {0};
                     /* for device not assigning static address, use pseudo address as identity */
+                    peer_irk = p_dev_rec->ble.keys.irk;
+                    local_irk = btm_cb.devcb.id_keys.irk;
+
+                    // do not enter IRK if peer or local device does not have privacy turned on
+                    // disable, assume IRK indicate privacy could be enabled at any point,
+                    // warning: this could take up unnecessary spot in controller resolving list,
+                    // and could possible degrade performance; this could prevent conneccting
+                    // to peripheral device which has privacy disabled but IRK delivered per
+                    // standard privacy 1.2 requirement. Need FW mixed mode support to connect
+                    // to both RPA and static address.
                     if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) == 0)
                     {
                         memcpy(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
                         p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
                     }
 
+                    BTM_TRACE_DEBUG("%s:adding device to controller resolving list", __func__);
+                    // use identical IRK for now
                     rt = btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
-                              p_dev_rec->ble.static_addr, peer_irk, local_irk); // use identical IRK for now 
+                              p_dev_rec->ble.static_addr, peer_irk, local_irk);
                 }
-               else
-               {
+                else
+                {
                     UINT8 param[40] = {0};
                     UINT8 *p = param;
 
@@ -593,16 +649,16 @@
                     BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
 
                     if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
-                                                    BTM_BLE_META_ADD_IRK_LEN,
-                                                    param,
-                                                    btm_ble_resolving_list_vsc_op_cmpl)
-                                                    == BTM_CMD_STARTED)
+                                                   BTM_BLE_META_ADD_IRK_LEN,
+                                                   param,
+                                                   btm_ble_resolving_list_vsc_op_cmpl)
+                                                   == BTM_CMD_STARTED)
                         rt = TRUE;
-               }
+                }
 
                if (rt)
-                    btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
-                                                       BTM_BLE_META_ADD_IRK_ENTRY);
+                   btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+                                                      BTM_BLE_META_ADD_IRK_ENTRY);
             }
         }
         else
@@ -631,14 +687,17 @@
 *******************************************************************************/
 void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
 {
-    btm_ble_update_resolving_list( p_dev_rec->bd_addr, FALSE);
+    btm_ble_update_resolving_list(p_dev_rec->bd_addr, FALSE);
 
     if ((p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
         btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
                                                   BTM_BLE_META_REMOVE_IRK_ENTRY) == FALSE)
     {
+        btm_ble_update_resolving_list( p_dev_rec->bd_addr, FALSE);
         btm_ble_remove_resolving_list_entry(p_dev_rec);
-    } else {
+    }
+    else
+    {
         BTM_TRACE_DEBUG("Device not in resolving list");
     }
 }
@@ -679,6 +738,10 @@
 *******************************************************************************/
 void btm_ble_disable_resolving_list(void)
 {
+    /* if controller does not support RPA offloading or privacy 1.2, skip */
+    if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+        return;
+
     if (btm_cb.ble_ctr_cb.enabled)
     {
         if (!controller_get_interface()->supports_ble_privacy())
@@ -725,7 +788,7 @@
 BOOLEAN btm_ble_resolving_list_empty(void)
 {
     return (controller_get_interface()->get_ble_resolving_list_max_size() ==
-                                    btm_cb.ble_ctr_cb.resolving_list_avail_size);
+            btm_cb.ble_ctr_cb.resolving_list_avail_size);
 }
 
 /*******************************************************************************
@@ -752,7 +815,6 @@
             btm_ble_enable_resolving_list();
         else
             btm_ble_disable_resolving_list();
-
         return;
     }
 
@@ -782,13 +844,18 @@
 *******************************************************************************/
 void btm_ble_resolving_list_init(UINT8 max_irk_list_sz)
 {
-    tBTM_BLE_RESOLVE_Q          *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+    tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+    UINT8 irk_mask_size =  (max_irk_list_sz % 8) ?
+                           (max_irk_list_sz/8 + 1) : (max_irk_list_sz/8);
 
     if (max_irk_list_sz > 0)
     {
-        p_q->resolve_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) *
-                                                  max_irk_list_sz);
-        p_q->resolve_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz);
+        p_q->resolve_q_random_pseudo = (BD_ADDR *)GKI_getbuf(sizeof(BD_ADDR) * max_irk_list_sz);
+        p_q->resolve_q_action = (UINT8 *)GKI_getbuf(max_irk_list_sz);
+
+        /* RPA offloading feature */
+        if (btm_cb.ble_ctr_cb.irk_list_mask == NULL)
+            btm_cb.ble_ctr_cb.irk_list_mask = (UINT8 *)GKI_getbuf(irk_mask_size);
 
         BTM_TRACE_DEBUG ("%s max_irk_list_sz = %d", __func__, max_irk_list_sz);
     }
@@ -810,7 +877,7 @@
 *******************************************************************************/
 void btm_ble_resolving_list_cleanup(void)
 {
-    tBTM_BLE_RESOLVE_Q          *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+    tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
 
     if (p_q->resolve_q_random_pseudo)
         GKI_freebuf(p_q->resolve_q_random_pseudo);
@@ -819,5 +886,9 @@
        GKI_freebuf(p_q->resolve_q_action);
 
     controller_get_interface()->set_ble_resolving_list_max_size(0);
+    if (btm_cb.ble_ctr_cb.irk_list_mask)
+       GKI_freebuf(btm_cb.ble_ctr_cb.irk_list_mask);
+
+    btm_cb.ble_ctr_cb.irk_list_mask = NULL;
 }
 #endif
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 3053dbe..faae4f5 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -155,6 +155,7 @@
 #endif
 
     p_dev_rec->rmt_io_caps = io_cap;
+    p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
 
     return(TRUE);
 }
@@ -427,18 +428,26 @@
 ** Returns          Pointer to the record or NULL
 **
 *******************************************************************************/
-tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr)
+tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr)
 {
     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
-    int i;
 
     if (bd_addr)
     {
-        for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
+        for (uint8_t i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
         {
-            if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
-                && (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN)))
-                return(p_dev_rec);
+            if (p_dev_rec->sec_flags & BTM_SEC_IN_USE)
+            {
+                if (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN))
+                    return(p_dev_rec);
+
+                // If a LE random address is looking for device record
+                if (!memcmp(p_dev_rec->ble.pseudo_addr, bd_addr, BD_ADDR_LEN))
+                    return (p_dev_rec);
+
+                if (btm_ble_addr_resolvable(bd_addr, p_dev_rec))
+                    return(p_dev_rec);
+            }
         }
     }
     return(NULL);
@@ -446,6 +455,59 @@
 
 /*******************************************************************************
 **
+** Function         btm_consolidate_dev
+**
+** Description      combine security records if identified as same peer
+**
+** Returns          none
+**
+*******************************************************************************/
+void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
+{
+    tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+    tBTM_SEC_DEV_REC temp_rec = *p_target_rec;
+    BD_ADDR dummy_bda = {0};
+
+    BTM_TRACE_DEBUG("%s", __func__);
+
+    for (uint8_t i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
+    {
+        if (p_target_rec!= p_dev_rec && p_dev_rec->sec_flags & BTM_SEC_IN_USE)
+        {
+            if (!memcmp (p_dev_rec->bd_addr, p_target_rec->bd_addr, BD_ADDR_LEN))
+            {
+                memcpy(p_target_rec, p_dev_rec, sizeof(tBTM_SEC_DEV_REC));
+                p_target_rec->ble = temp_rec.ble;
+                p_target_rec->enc_key_size = temp_rec.enc_key_size;
+                p_target_rec->ble_hci_handle = temp_rec.ble_hci_handle;
+                p_target_rec->conn_params = temp_rec.conn_params;
+                p_target_rec->device_type |= temp_rec.device_type;
+                p_target_rec->sec_flags |= temp_rec.sec_flags;
+
+                p_target_rec->new_encryption_key_is_p256 = temp_rec.new_encryption_key_is_p256;
+                p_target_rec->no_smp_on_br = temp_rec.no_smp_on_br;
+                /* mark the combined record as unused */
+                p_dev_rec->sec_flags &= ~BTM_SEC_IN_USE;
+                break;
+            }
+
+            /* an RPA device entry is a duplicate of the target record */
+            if (btm_ble_addr_resolvable(p_dev_rec->bd_addr, p_target_rec))
+            {
+                if (memcmp(p_target_rec->ble.pseudo_addr, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)
+                {
+                    p_target_rec->ble.ble_addr_type = p_dev_rec->ble.ble_addr_type;
+                    p_target_rec->device_type |= p_dev_rec->device_type;
+                    p_dev_rec->sec_flags &= ~BTM_SEC_IN_USE;
+                }
+                break;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btm_find_or_alloc_dev
 **
 ** Description      Look for the record in the device database for the record
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index ec0a03f..a8a1090 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -467,6 +467,7 @@
 
 typedef struct
 {
+    BD_ADDR pseudo_addr; /* LE pseudo address of the device if different from device address  */
     tBLE_ADDR_TYPE      ble_addr_type;  /* LE device type: public or random address */
     tBLE_ADDR_TYPE      static_addr_type;   /* static address type */
     BD_ADDR             static_addr;    /* static address */
@@ -585,6 +586,9 @@
                                                     ** Link encrypted with such LK can be used
                                                     ** for SM over BR/EDR.
                                                     */
+    BOOLEAN no_smp_on_br;       /* if set to TRUE then SMP on BR/EDR doesn't */
+                                /* work, i.e. link keys crosspairing */
+                                /* SC BR/EDR->SC LE doesn't happen */
 #endif
 
 // btla-specific ++
@@ -1004,10 +1008,10 @@
 extern void btm_ble_add_2_white_list_complete(UINT8 status);
 extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
 extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern BOOLEAN btm_ble_addr_resolvable(BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec);
 extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
 extern BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
 extern void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
-extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
 #endif  /* BLE_INCLUDED */
 
 /* Vendor Specific Command complete evt handler */
@@ -1070,7 +1074,9 @@
 extern void  btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC  *p_dev_rec);
 extern  BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC **p_rec);
 extern BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
+extern void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec);
 extern BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
+extern BOOLEAN btm_ble_init_pseudo_addr (tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR new_pseudo_addr);
 #endif /* BLE_INCLUDED */
 
 extern tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda);
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index c806782..33d0efc 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -995,6 +995,7 @@
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     if (transport == BT_TRANSPORT_LE)
     {
+        btm_ble_init_pseudo_addr (p_dev_rec, bd_addr);
         p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK;
 
         if (SMP_Pair(bd_addr) == SMP_STARTED)
@@ -4058,20 +4059,25 @@
         else
         {
             BTM_TRACE_DEBUG ("TRYING TO DECIDE IF CAN USE SMP_BR_CHNL");
-            if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec)))
+            if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec))
+                /* no LE keys are available, do deriving */
+                 && (!(p_dev_rec->sec_flags &BTM_SEC_LE_LINK_KEY_KNOWN) ||
+                /* or BR key is higher security than existing LE keys */
+                 (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED) &&
+                 (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED))))
             {
                 BTM_TRACE_DEBUG ("link encrypted afer dedic bonding can use SMP_BR_CHNL");
 
                 if (btm_sec_is_master(p_dev_rec))
                 {
-                    // Encryption is required to start SM over BR/EDR.
-                    // Indicate that this is encryption after authentication.
+                    // Encryption is required to start SM over BR/EDR
+                    // indicate that this is encryption after authentication
                     BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL);
                 }
             }
-
             l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
         }
+
         return;
     }
 
@@ -4150,7 +4156,8 @@
 
     /* For transaction collision we need to wait and repeat.  There is no need */
     /* for random timeout because only slave should receive the result */
-    if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || (status == HCI_ERR_DIFF_TRANSACTION_COLLISION))
+    if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) ||
+        (status == HCI_ERR_DIFF_TRANSACTION_COLLISION))
     {
         btm_sec_auth_collision(handle);
         return;
@@ -4181,15 +4188,14 @@
     BTM_TRACE_DEBUG ("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
 
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
-    if (acl_idx != MAX_L2CAP_LINKS )
+    if (acl_idx != MAX_L2CAP_LINKS)
         p_acl = &btm_cb.acl_db[acl_idx];
 
     btm_sec_check_pending_enc_req (p_dev_rec, p_acl->transport, encr_enable);
 
     if (p_acl && p_acl->transport == BT_TRANSPORT_LE)
     {
-        if (status == HCI_ERR_KEY_MISSING ||
-            status == HCI_ERR_AUTH_FAILURE ||
+        if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE ||
             status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
         {
             p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN);
@@ -4199,29 +4205,44 @@
         return;
     }
     else
+    {
         /* BR/EDR connection, update the encryption key size to be 16 as always */
         p_dev_rec->enc_key_size = 16;
+    }
 
-    BTM_TRACE_DEBUG ("in btm_sec_encrypt_change new_encr_key_256 is %d",
-                       p_dev_rec->new_encryption_key_is_p256);
+     BTM_TRACE_DEBUG ("in %s new_encr_key_256 is %d",
+                       __func__, p_dev_rec->new_encryption_key_is_p256);
 
     if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle))
     {
         if (p_dev_rec->new_encryption_key_is_p256)
         {
             if (btm_sec_use_smp_br_chnl(p_dev_rec) &&
-                btm_sec_is_master(p_dev_rec))
+                btm_sec_is_master(p_dev_rec) &&
+                /* if LE key is not known, do deriving */
+                (!(p_dev_rec->sec_flags &BTM_SEC_LE_LINK_KEY_KNOWN) ||
+                /* or BR key is higher security than existing LE keys */
+                 (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
+                 && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED))))
             {
                 /* BR/EDR is encrypted with LK that can be used to derive LE LTK */
                 p_dev_rec->new_encryption_key_is_p256 = FALSE;
 
-                BTM_TRACE_DEBUG ("btm_sec_encrypt_change start SM over BR/EDR");
-                SMP_BR_PairWith(p_dev_rec->bd_addr);
+                if (p_dev_rec->no_smp_on_br)
+                {
+                    BTM_TRACE_DEBUG ("%s NO SM over BR/EDR", __func__);
+                }
+                else
+                {
+                    BTM_TRACE_DEBUG ("%s start SM over BR/EDR", __func__);
+                    SMP_BR_PairWith(p_dev_rec->bd_addr);
+                }
             }
         }
         else
-        {   /* BR/EDR is successfully encrypted. Correct LK type if needed
-              (BR/EDR LK derived from LE LTK was used for encryption) */
+        {
+            // BR/EDR is successfully encrypted. Correct LK type if needed
+            // (BR/EDR LK derived from LE LTK was used for encryption)
             if ((encr_enable == 1)  && /* encryption is ON for SSP */
                 /* LK type is for BR/EDR SC */
                 (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256 ||
@@ -4254,7 +4275,6 @@
     }
 
     p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
-
     /* If encryption setup failed, notify the waiting layer */
     if (status != HCI_SUCCESS)
     {
@@ -4264,7 +4284,6 @@
 
     /* Encryption setup succeeded, execute the next security procedure, if any */
     status = (UINT8)btm_sec_execute_procedure (p_dev_rec);
-
     /* If there is no next procedure, or procedure failed to start, notify the caller */
     if (status != BTM_CMD_STARTED)
         btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
@@ -4808,23 +4827,22 @@
                                                    p_link_key, p_dev_rec->link_key_type);
         }
     }
-#if BTM_CROSS_TRANSP_KEY_DERIVATION == TRUE
     else
     {
         if ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256) ||
             (p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256))
         {
-             p_dev_rec->new_encr_key_256 = TRUE;
+             p_dev_rec->new_encryption_key_is_p256 = TRUE;
              BTM_TRACE_DEBUG ("%s set new_encr_key_256 to %d",
-                               __func__, p_dev_rec->new_encr_key_256);
+                               __func__, p_dev_rec->new_encryption_key_is_p256);
         }
     }
-#endif
 
     /* If name is not known at this point delay calling callback until the name is   */
     /* resolved. Unless it is a HID Device and we really need to send all link keys. */
     if ((!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
-        &&  ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL)) )
+        &&  ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL))
+        && !ltk_derived_lk)
     {
         BTM_TRACE_EVENT ("btm_sec_link_key_notification()  Delayed BDA: %08x%04x Type:%d",
                           (p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3],
@@ -4846,7 +4864,9 @@
     /* If its not us who perform authentication, we should tell stackserver */
     /* that some authentication has been completed                          */
     /* This is required when different entities receive link notification and auth complete */
-    if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE))
+    if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)
+        /* for derived key, always send authentication callback for BR channel */
+         || ltk_derived_lk)
     {
         if (btm_cb.api.p_auth_complete_callback)
             (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
@@ -4860,8 +4880,17 @@
     {
         if (btm_cb.api.p_link_key_callback)
         {
-            (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,  p_dev_rec->sec_bd_name,
-                                               p_link_key, p_dev_rec->link_key_type);
+            if (ltk_derived_lk)
+            {
+                BTM_TRACE_DEBUG ("btm_sec_link_key_notification()  LTK derived LK is saved already"
+                                    " (key_type = %d)", p_dev_rec->link_key_type);
+            }
+            else
+            {
+                (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,
+                                                   p_dev_rec->sec_bd_name,
+                                                   p_link_key, p_dev_rec->link_key_type);
+            }
         }
     }
 }
@@ -5839,12 +5868,15 @@
 void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_transport)
 {
     tBTM_SEC_CALLBACK   *p_callback = p_dev_rec->p_callback;
-    tBT_TRANSPORT transport = is_le_transport ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR;
 
     if (p_dev_rec->p_callback)
     {
         p_dev_rec->p_callback = NULL;
-        (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, res);
+
+        if (is_le_transport)
+           (*p_callback) (p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE, p_dev_rec->p_ref_data, res);
+        else
+           (*p_callback) (p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, p_dev_rec->p_ref_data, res);
     }
 
     btm_sec_check_pending_reqs();
@@ -6214,11 +6246,8 @@
     BOOLEAN le_capable = FALSE;
 
 #if (BLE_INCLUDED== TRUE)
-    if (p_dev_rec && ((p_dev_rec->device_type == BT_DEVICE_TYPE_DUMO) ||
-         (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) ) )
-    {
+    if (p_dev_rec && (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE)
         le_capable  = TRUE;
-    }
 #endif
     return le_capable;
 }
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index de0b195..a4d1ba3 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -1399,6 +1399,10 @@
 #define BTM_AUTH_BONDS      6   /* the general/dedicated bonding bits  */
 #define BTM_AUTH_YN_BIT     1   /* this is the Yes or No bit  */
 
+#define BTM_BLE_INITIATOR_KEY_SIZE 15
+#define BTM_BLE_RESPONDER_KEY_SIZE 15
+#define BTM_BLE_MAX_KEY_SIZE       16
+
 typedef UINT8 tBTM_AUTH_REQ;
 
 enum
@@ -1613,9 +1617,10 @@
 /* data type for tBTM_LE_COMPLT */
 typedef struct
 {
-    UINT8       reason;
-    UINT8       sec_level;
-    BOOLEAN     is_pair_cancel;
+    UINT8 reason;
+    UINT8 sec_level;
+    BOOLEAN is_pair_cancel;
+    BOOLEAN smp_over_br;
 }tBTM_LE_COMPLT;
 #endif
 
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 37669b4..62ef1db 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -203,6 +203,14 @@
 #define SMP_SEC_DEFAULT_KEY      (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | \
                                   SMP_SEC_KEY_TYPE_CSRK | SMP_SEC_KEY_TYPE_LK)
 
+#define SMP_SC_KEY_STARTED      0   /* passkey entry started */
+#define SMP_SC_KEY_ENTERED      1   /* passkey digit entered */
+#define SMP_SC_KEY_ERASED       2   /* passkey digit erased */
+#define SMP_SC_KEY_CLEARED      3   /* passkey cleared */
+#define SMP_SC_KEY_COMPLT       4   /* passkey entry completed */
+#define SMP_SC_KEY_OUT_OF_RANGE 5   /* out of range */
+typedef UINT8 tSMP_SC_KEY_TYPE;
+
 /* data type for BTM_SP_IO_REQ_EVT */
 typedef struct
 {
@@ -216,9 +224,10 @@
 
 typedef struct
 {
-    tSMP_STATUS       reason;
-    tSMP_SEC_LEVEL    sec_level;
-    BOOLEAN     is_pair_cancel;
+    tSMP_STATUS reason;
+    tSMP_SEC_LEVEL sec_level;
+    BOOLEAN is_pair_cancel;
+    BOOLEAN smp_over_br;
 } tSMP_CMPL;
 
 typedef struct
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index fa2fcce..97bf58d 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -424,16 +424,21 @@
         if (p_lcb->ccb_queue.p_first_ccb != NULL || p_lcb->p_pending_ccb)
         {
             L2CAP_TRACE_DEBUG("l2c_link_hci_disc_comp: Restarting pending ACL request");
+            transport = p_lcb->transport;
 #if BLE_INCLUDED == TRUE
             /* for LE link, always drop and re-open to ensure to get LE remote feature */
             if (p_lcb->transport == BT_TRANSPORT_LE)
             {
-                BD_ADDR bd_addr;
-                memcpy(bd_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
-                l2cu_release_lcb (p_lcb);
-                // make sure Tx credit allocation is redistributed in between links by calling l2cu_allocate_lcb
-                p_lcb = l2cu_allocate_lcb (bd_addr, FALSE, BT_TRANSPORT_LE);
-                transport = BT_TRANSPORT_LE;
+                l2cb.is_ble_connecting = FALSE;
+                btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
+                /* Release any held buffers */
+                BT_HDR *p_buf;
+                while (!list_is_empty(p_lcb->link_xmit_data_q))
+                {
+                    p_buf = list_front(p_lcb->link_xmit_data_q);
+                    list_remove(p_lcb->link_xmit_data_q, p_buf);
+                    GKI_freebuf(p_buf);
+                }
             }
             else
 #endif
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 634f1cd..212d5df 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -186,6 +186,11 @@
     STREAM_TO_UINT16 (l2cap_len, p);
     STREAM_TO_UINT16 (rcv_cid, p);
 
+   /* for BLE channel, always notify connection when ACL data received on the link */
+   if (p_lcb && p_lcb->transport == BT_TRANSPORT_LE && p_lcb->link_state != LST_DISCONNECTING)
+      /* only process fixed channel data as channel open indication when link is not in disconnecting mode */
+        l2cble_notify_le_connection(p_lcb->remote_bd_addr);
+
     /* Find the CCB for this CID */
     if (rcv_cid >= L2CAP_BASE_APPL_CID)
     {
@@ -261,14 +266,10 @@
         counter_add("l2cap.fix.rx.pkts", 1);
         /* If no CCB for this channel, allocate one */
         if (p_lcb &&
-            /* discard fixed channel data when link is disconnecting */
+            /* only process fixed channel data when link is open or wait for data indication */
             (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))
+            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))
-            l2cble_notify_le_connection(p_lcb->remote_bd_addr);
-#endif
             p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL];
 
             if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 397a2ca..f1c6936 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -46,7 +46,7 @@
     smp_generate_ltk,
     smp_send_id_info,
     smp_generate_csrk,
-    smp_derive_link_key_from_long_term_key
+    smp_set_derive_link_key
 };
 
 /*******************************************************************************
@@ -58,7 +58,8 @@
     SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x",
         __func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key);
 
-    if (((p_cb->le_secure_connections_mode_is_used) || (p_cb->smp_over_br)) &&
+    if (((p_cb->le_secure_connections_mode_is_used) ||
+        (p_cb->smp_over_br)) &&
         ((key_type == SMP_SEC_KEY_TYPE_ENC) || (key_type == SMP_SEC_KEY_TYPE_LK)))
     {
         /* in LE SC mode LTK, CSRK and BR/EDR LK are derived locally instead of
@@ -176,11 +177,9 @@
                         p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
                     }
 
-#if BTM_CROSS_TRANSP_KEY_DERIVATION == FALSE
                     SMP_TRACE_WARNING ("Cross transport key derivation is not supported");
                     p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
                     p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
-#endif
 
                     SMP_TRACE_WARNING("set auth_req: 0x%02x, local_i_key: 0x%02x, local_r_key: 0x%02x",
                         p_cb->loc_auth_req, p_cb->local_i_key, p_cb->local_r_key);
@@ -986,6 +985,11 @@
     STREAM_TO_BDADDR(pid_key.static_addr, p);
     memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
 
+    /* to use as BD_ADDR for lk derived from ltk */
+    p_cb->id_addr_rcvd = TRUE;
+    p_cb->id_addr_type = pid_key.addr_type;
+    memcpy(p_cb->id_addr, pid_key.static_addr, BD_ADDR_LEN);
+
     /* store the ID key from peer device */
     if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
         btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
@@ -1217,8 +1221,8 @@
     SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
                       __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
 
-    if (p_cb->role == HCI_ROLE_SLAVE||
-        (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
+    if (p_cb->role == HCI_ROLE_SLAVE ||
+       (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
     {
         smp_key_pick_key(p_cb, p_data);
     }
@@ -1228,6 +1232,12 @@
         /* state check to prevent re-entrant */
         if (smp_get_state() == SMP_STATE_BOND_PENDING)
         {
+            if (p_cb->derive_lk)
+            {
+                smp_derive_link_key_from_long_term_key(p_cb, NULL);
+                p_cb->derive_lk = FALSE;
+            }
+
             if (p_cb->total_tx_unacked == 0)
                 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
             else
@@ -1976,6 +1986,25 @@
 
 /*******************************************************************************
 **
+** Function         smp_set_derive_link_key
+**
+** Description      This function is called to set flag that indicates that
+**                  BR/EDR LK has to be derived from LTK after all keys are
+**                  distributed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_set_derive_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG ("%s", __func__);
+    p_cb->derive_lk = TRUE;
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
+    smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
 ** Function         smp_derive_link_key_from_long_term_key
 **
 ** Description      This function is called to derive BR/EDR LK from LTK.
@@ -1996,7 +2025,6 @@
     }
 
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
-
     SMP_TRACE_DEBUG("%s successfully completed", __FUNCTION__);
     smp_key_distribution(p_cb, NULL);
 }
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 24aa3ec..52b0301 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -270,6 +270,10 @@
     UINT8           trace_level;
     BD_ADDR         pairing_bda;
     tSMP_STATE      state;
+    BOOLEAN         derive_lk;
+    BOOLEAN         id_addr_rcvd;
+    tBLE_ADDR_TYPE  id_addr_type;
+    BD_ADDR         id_addr;
     BOOLEAN         smp_over_br;
     tSMP_BR_STATE   br_state;           /* if SMP over BR/ERD has priority over SMP */
     UINT8           failure;
@@ -305,8 +309,9 @@
                                             /* either in Secure Connections mode or not at all */
     tSMP_ASSO_MODEL selected_association_model;
     BOOLEAN         le_secure_connections_mode_is_used;
-    tBTM_SP_KEY_TYPE  local_keypress_notification;
-    tBTM_SP_KEY_TYPE  peer_keypress_notification;
+    BOOLEAN le_sc_kp_notif_is_used;
+    tSMP_SC_KEY_TYPE local_keypress_notification;
+    tSMP_SC_KEY_TYPE peer_keypress_notification;
     UINT8           round;       /* authentication stage 1 round for passkey association model */
     UINT32          number_to_display;
     BT_OCTET16      mac_key;
@@ -447,9 +452,10 @@
 extern void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_process_secure_connection_long_term_key(void);
-extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_derive_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index 47d0125..f301530 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -1926,9 +1926,27 @@
 BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb)
 {
     tBTM_SEC_DEV_REC *p_dev_rec;
+    BD_ADDR bda_for_lk;
+    tBLE_ADDR_TYPE conn_addr_type;
 
     SMP_TRACE_DEBUG ("%s", __func__);
 
+    if (p_cb->id_addr_rcvd && p_cb->id_addr_type == BLE_ADDR_PUBLIC)
+    {
+        SMP_TRACE_DEBUG ("Use rcvd identity address as BD_ADDR of LK rcvd identity address");
+        memcpy(bda_for_lk, p_cb->id_addr, BD_ADDR_LEN);
+    }
+    else if ((BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, bda_for_lk, &conn_addr_type)) &&
+              conn_addr_type == BLE_ADDR_PUBLIC)
+    {
+        SMP_TRACE_DEBUG ("Use rcvd connection address as BD_ADDR of LK");
+    }
+    else
+    {
+        SMP_TRACE_WARNING ("Don't have peer public address to associate with LK");
+        return FALSE;
+    }
+
     if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
     {
         SMP_TRACE_ERROR("%s failed to find Security Record", __func__);
@@ -1989,7 +2007,7 @@
         p = notif_link_key;
         ARRAY16_TO_STREAM(p, link_key);
 
-        btm_sec_link_key_notification (p_cb->pairing_bda, notif_link_key, link_key_type);
+        btm_sec_link_key_notification (bda_for_lk, notif_link_key, link_key_type);
 
         SMP_TRACE_EVENT ("%s is completed", __func__);
     }
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 9f2e532..3e592f2 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -942,6 +942,7 @@
     SMP_TRACE_DEBUG ("smp_proc_pairing_cmpl ");
 
     evt_data.cmplt.reason = p_cb->status;
+    evt_data.cmplt.smp_over_br = p_cb->smp_over_br;
 
     if (p_cb->status == SMP_SUCCESS)
         evt_data.cmplt.sec_level = p_cb->sec_level;