LE fixes

- Null pointer exception check added.

An exception occurs at the memcpy in the bta_dm_gatt_disc_result.
User removed the battery on Ble device(Smart Nudge) during bonding
and connection. This exception occurs sometimes.
I used Broadcom LE Explorer to reproduce it.

- Fixed disconnect and encryption behaviour

Disconnect will now disconnect the physical link immediately when no
other application is interested in the device anymore. Also, the
connection to a remote device is now dropped if encryption fails.

- Deep copy buffers when transfering context

Certain BTA server event types require a deep copy of the request
data buffers when transfering context. Shallow copy of the pointers
involved may cause a crash when overlapping read and write requests
are received.

- 2nd encryption has not started

need to send encryption complete callback
when the encryption fail due to link drop without a complete event.
Otherwise BTA layer would not be able to clean up the status,
and no further encryption can be started.

Change-Id: If93e0a188e8779830c8991e4193b96dc95e23e5d
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 0ade1cc..63f81d2 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -4978,10 +4978,17 @@
     {
         APPL_TRACE_DEBUG3("ADDING BLE SERVICE uuid=0x%x, ble_ptr = 0x%x, ble_raw_used = 0x%x", service_id.uuid.uu.uuid16,bta_dm_search_cb.p_ble_rawdata,bta_dm_search_cb.ble_raw_used);
 
-        memcpy((bta_dm_search_cb.p_ble_rawdata + bta_dm_search_cb.ble_raw_used), &service_id,
-                sizeof(service_id) );
+        if(bta_dm_search_cb.p_ble_rawdata)
+        {
+            memcpy((bta_dm_search_cb.p_ble_rawdata + bta_dm_search_cb.ble_raw_used), &service_id,
+                   sizeof(service_id) );
 
-        bta_dm_search_cb.ble_raw_used += sizeof(service_id);
+            bta_dm_search_cb.ble_raw_used += sizeof(service_id);
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("p_ble_rawdata is NULL");
+        }
 
     }
     else
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 25260f9..23337ec 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -712,10 +712,7 @@
     cb_data.close.reason    = p_clcb->reason;
     bdcpy(cb_data.close.remote_bda, p_clcb->bda);
 
-    if (p_clcb->status == BTA_GATT_OK)
-    {
-        bta_gattc_clcb_dealloc(p_clcb);
-    }
+    bta_gattc_clcb_dealloc(p_clcb);
 
     ( * p_cback)(BTA_GATTC_CLOSE_EVT,   (tBTA_GATTC *)&cb_data);
 
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
index 7b87afe..775d6b4 100644
--- a/bta/gatt/bta_gattc_cache.c
+++ b/bta/gatt/bta_gattc_cache.c
@@ -470,8 +470,6 @@
 
         if (param.s_handle > param.e_handle)
         {
-            APPL_TRACE_ERROR2("discover range invalid: [0x%04x ~ 0x%04x]", param.s_handle, param.e_handle);
-
             return GATT_ERROR;
         }
     }
@@ -489,8 +487,6 @@
 *******************************************************************************/
 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
 {
-    APPL_TRACE_DEBUG0("starting discovery included service");
-
     return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
 }
 /*******************************************************************************
@@ -506,8 +502,6 @@
 {
     p_srvc_cb->total_char = 0;
 
-    APPL_TRACE_DEBUG0("starting discover characteristics");
-
     return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
 }
 /*******************************************************************************
@@ -606,8 +600,6 @@
 {
     tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
 
-    APPL_TRACE_DEBUG1("Total %d Char found ", p_srvc_cb->total_char);
-
     /* if there are characteristic needs to be explored */
     if (p_srvc_cb->total_char > 0)
     {
@@ -709,7 +701,7 @@
     tBTA_GATTC_ATTR_REC *p_rec = NULL;
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
 
-    if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+    if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
     {
         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
 
@@ -731,7 +723,7 @@
     {   /* allocate bigger buffer ?? */
         status = GATT_DB_FULL;
 
-        APPL_TRACE_ERROR0("char not added, no resources");
+        APPL_TRACE_ERROR0("service not added, no resources or wrong state");
     }
     return status;
 }
@@ -913,10 +905,11 @@
 {
     tBTA_GATTC_SERV * p_srvc_cb = NULL;
     BOOLEAN          pri_srvc;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
 
-    if (p_srvc_cb != NULL)
+    if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST)
     {
         switch (disc_type)
         {
@@ -981,7 +974,8 @@
 
     if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
     {
-        p_clcb->status = status;
+        if (p_clcb->status == GATT_SUCCESS)
+            p_clcb->status = status;
         bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
         return;
     }
@@ -1080,7 +1074,7 @@
                         if (bta_gattc_uuid_compare(descr_uuid, attr_uuid, TRUE))
                         {
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                            APPL_TRACE_DEBUG0("found descripotor!!");
+                            APPL_TRACE_DEBUG0("found descriptor!!");
 #endif
                             handle = p_attr->attr_handle;
                             done = TRUE;
@@ -1335,7 +1329,9 @@
                             attr_type == p_attr->attr_type)
                         {
 
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
                             APPL_TRACE_DEBUG0("found char handle mapping characteristic");
+#endif
                             p_result->inst_id = p_attr->inst_id;
 
                             if (p_param != NULL)
@@ -1354,10 +1350,12 @@
                 }
                 p_attr = p_attr->p_next;
             }
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
             if (status)
             {
                 APPL_TRACE_ERROR0("In the given service, can not find matching record");
             }
+#endif
             break;
         }
 
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index 767cd0f..5a7cccd 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -2256,9 +2256,8 @@
         /*Map the HCI fail reason  to  bt status  */
         switch (p_auth_cmpl->fail_reason)
         {
-
-            btif_dm_remove_ble_bonding_keys();
             default:
+                btif_dm_remove_ble_bonding_keys();
                 status =  BT_STATUS_FAIL;
                 break;
         }
diff --git a/btif/src/btif_gatt_server.c b/btif/src/btif_gatt_server.c
index 9de36f9..a7ccf0b 100644
--- a/btif/src/btif_gatt_server.c
+++ b/btif/src/btif_gatt_server.c
@@ -39,6 +39,7 @@
 
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
 
+#include "gki.h"
 #include "bta_api.h"
 #include "bta_gatt_api.h"
 #include "bd.h"
@@ -116,6 +117,54 @@
 **  Static functions
 ************************************************************************************/
 
+static void btapp_gatts_copy_req_data(UINT16 event, char *p_dest, char *p_src)
+{
+    tBTA_GATTS *p_dest_data = (tBTA_GATTS*) p_dest;
+    tBTA_GATTS *p_src_data = (tBTA_GATTS*) p_src;
+
+    if (!p_src_data || !p_dest_data)
+        return;
+
+    // Copy basic structure first
+    memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
+
+    // Allocate buffer for request data if necessary
+    switch (event)
+    {
+        case BTA_GATTS_READ_EVT:
+        case BTA_GATTS_WRITE_EVT:
+        case BTA_GATTS_EXEC_WRITE_EVT:
+        case BTA_GATTS_MTU_EVT:
+            p_dest_data->req_data.p_data = GKI_getbuf(sizeof(tBTA_GATTS_REQ_DATA));
+            if (p_dest_data->req_data.p_data != NULL)
+            {
+                memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
+                    sizeof(tBTA_GATTS_REQ_DATA));
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void btapp_gatts_free_req_data(UINT16 event, tBTA_GATTS *p_data)
+{
+    switch (event)
+    {
+        case BTA_GATTS_READ_EVT:
+        case BTA_GATTS_WRITE_EVT:
+        case BTA_GATTS_EXEC_WRITE_EVT:
+        case BTA_GATTS_MTU_EVT:
+            if (p_data && p_data->req_data.p_data)
+                GKI_freebuf(p_data->req_data.p_data);
+            break;
+
+        default:
+            break;
+    }
+}
+
 static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
 {
     ALOGD("%s: Event %d", __FUNCTION__, event);
@@ -284,13 +333,15 @@
             ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
             break;
     }
+
+    btapp_gatts_free_req_data(event, p_data);
 }
 
 static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
 {
     bt_status_t status;
     status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
-        (void*)p_data, sizeof(tBTA_GATTS), NULL);
+        (void*)p_data, sizeof(tBTA_GATTS), btapp_gatts_copy_req_data);
     ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
 }
 
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index a3cbc3d..34635a5 100644
--- a/btif/src/btif_gatt_util.c
+++ b/btif/src/btif_gatt_util.c
@@ -55,6 +55,8 @@
 
 static btif_gatt_encrypted_link_t encrypted_links[BTIF_GATT_MAX_ENC_LINK_RECORDS];
 
+extern bt_status_t btif_dm_remove_bond(const bt_bdaddr_t *bd_addr);
+
 int uuidType(unsigned char* p_uuid)
 {
     int i = 0;
@@ -330,7 +332,11 @@
     {
         btif_gatt_add_encrypted_link(bd_addr);
     } else {
+        bt_bdaddr_t bda;
+        bdcpy(bda.address, bd_addr);
+
         btif_gatt_remove_encrypted_link(bd_addr);
+        btif_dm_remove_bond(&bda);
     }
 }
 
@@ -348,4 +354,4 @@
         BTA_DmSetEncryption(bd_addr,
                             &btif_gatt_set_encryption_cb, BTM_BLE_SEC_ENCRYPT);
     }
-}
\ No newline at end of file
+}
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 1d2cdf3..0400df4 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -1198,12 +1198,17 @@
         if (!btsnd_hcic_ble_start_enc(p_rec->hci_handle, dummy_rand, 0, stk))
             return FALSE;
     }
-    else
+    else if (p_rec->ble.key_type & BTM_LE_KEY_PENC)
     {
         if (!btsnd_hcic_ble_start_enc(p_rec->hci_handle, p_rec->ble.keys.rand,
                                       p_rec->ble.keys.ediv, p_rec->ble.keys.ltk))
             return FALSE;
     }
+    else
+    {
+        return FALSE;
+    }
+
     return TRUE;
 }
 
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index 212b118..b2ffac5 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -4471,6 +4471,7 @@
     tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev_by_handle (handle);
     UINT8             old_pairing_flags = btm_cb.pairing_flags;
     int               result = HCI_ERR_AUTH_FAILURE;
+    tBTM_SEC_CALLBACK   *p_callback = NULL;
 
     /* If page was delayed for disc complete, can do it now */
     btm_cb.discing = FALSE;
@@ -4532,7 +4533,17 @@
     p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
 
     p_dev_rec->security_required = BTM_SEC_NONE;
-    p_dev_rec->p_callback = NULL; /* when the peer device time out the authentication before we do, this call back must be reset here */
+
+    p_callback = p_dev_rec->p_callback;
+
+    /* if security is pending, send callback to clean up the security state */
+    if(p_callback)
+    {
+        p_dev_rec->p_callback = NULL; /* when the peer device time out the authentication before
+                                         we do, this call back must be reset here */
+        (*p_callback) (p_dev_rec->bd_addr, p_dev_rec->p_ref_data, BTM_ERR_PROCESSING);
+    }
+
     BTM_TRACE_EVENT1("after Update sec_flags=0x%x", p_dev_rec->sec_flags);
 }
 
diff --git a/stack/l2cap/l2c_api.c b/stack/l2cap/l2c_api.c
index 691d386..30249a4 100644
--- a/stack/l2cap/l2c_api.c
+++ b/stack/l2cap/l2c_api.c
@@ -1489,6 +1489,12 @@
 
     p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = NULL;
     p_lcb->disc_reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
+
+#if BLE_INCLUDED == TRUE
+    if (fixed_cid == L2CAP_ATT_CID && !p_lcb->ccb_queue.p_first_ccb)
+        p_lcb->idle_timeout = 0;
+#endif
+
     l2cu_release_ccb (p_ccb);
 
     return (TRUE);