summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNitin Shivpure <nshivpur@codeaurora.org>2015-09-06 15:04:01 +0530
committerAndre Eisenbach <eisenbach@google.com>2015-09-24 11:28:50 -0700
commitbb2a4faddd9a7f03d13d37a23eb0da1ef52f9088 (patch)
tree2805a0630d53224467cd6ef7d54e69b9a7e4dff8
parent282091913b4ee3b26a2f79a630ecdca4e8ca89f6 (diff)
downloadandroid_system_bt-bb2a4faddd9a7f03d13d37a23eb0da1ef52f9088.tar.gz
android_system_bt-bb2a4faddd9a7f03d13d37a23eb0da1ef52f9088.tar.bz2
android_system_bt-bb2a4faddd9a7f03d13d37a23eb0da1ef52f9088.zip
Fix PAN crash due to fd mismatch
A case, where tap read thread is always exist, Sometimes data packets get recieved on older fd, which is not available. which is causing assert due to fd mismatch in race condition. when next pan connection is immediately available. If last pan connection gets disconnected, then tap_read_thread should be destroyed in btif context to fix this issue. Bug: 24093456 Change-Id: Ic1053200a7be4c2091d6c394634831ca3fbd61df
-rw-r--r--bta/pan/bta_pan_act.c4
-rw-r--r--btif/src/btif_pan.c60
2 files changed, 59 insertions, 5 deletions
diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c
index d4bd1c17d..4ed52e389 100644
--- a/bta/pan/bta_pan_act.c
+++ b/bta/pan/bta_pan_act.c
@@ -601,7 +601,6 @@ void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
if(p_data->conn.result == PAN_SUCCESS)
{
data.status = BTA_PAN_SUCCESS;
- bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr);
p_scb->pan_flow_enable = TRUE;
p_scb->app_flow_enable = TRUE;
bta_sys_conn_open(BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
@@ -648,7 +647,6 @@ void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
data.handle = p_data->hdr.layer_specific;
-
bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
/* free all queued up data buffers */
@@ -657,8 +655,6 @@ void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
GKI_init_q(&p_scb->data_queue);
- bta_pan_co_close(p_scb->handle, p_scb->app_id);
-
bta_pan_scb_dealloc(p_scb);
bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data);
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index c3dec2acc..cbb8d9745 100644
--- a/btif/src/btif_pan.c
+++ b/btif/src/btif_pan.c
@@ -273,10 +273,10 @@ static bt_status_t btpan_disconnect(const bt_bdaddr_t *bd_addr)
btpan_conn_t* conn = btpan_find_conn_addr(bd_addr->address);
if (conn && conn->handle >= 0)
{
- BTA_PanClose(conn->handle);
/* Inform the application that the disconnect has been initiated successfully */
btif_transfer_context(btif_in_pan_generic_evt, BTIF_PAN_CB_DISCONNECTING,
(char *)bd_addr, sizeof(bt_bdaddr_t), NULL);
+ BTA_PanClose(conn->handle);
return BT_STATUS_SUCCESS;
}
return BT_STATUS_FAIL;
@@ -488,6 +488,62 @@ btpan_conn_t* btpan_find_conn_addr(const BD_ADDR addr)
return NULL;
}
+static void btpan_open_conn(btpan_conn_t* conn, tBTA_PAN *p_data)
+{
+ BTIF_TRACE_API("btpan_open_conn: local_role:%d, peer_role: %d, handle:%d, conn: %p",
+ p_data->open.local_role, p_data->open.peer_role, p_data->open.handle, conn);
+
+ if (conn == NULL)
+ conn = btpan_new_conn(p_data->open.handle, p_data->open.bd_addr, p_data->open.local_role,
+ p_data->open.peer_role);
+ if (conn)
+ {
+ BTIF_TRACE_DEBUG("btpan_open_conn:tap_fd:%d, open_count:%d, "
+ "conn->handle:%d should = handle:%d, local_role:%d, remote_role:%d",
+ btpan_cb.tap_fd, btpan_cb.open_count, conn->handle, p_data->open.handle,
+ conn->local_role, conn->remote_role);
+
+ btpan_cb.open_count++;
+ conn->handle = p_data->open.handle;
+ if (btpan_cb.tap_fd < 0)
+ {
+ btpan_cb.tap_fd = btpan_tap_open();
+ if(btpan_cb.tap_fd >= 0)
+ create_tap_read_thread(btpan_cb.tap_fd);
+ }
+
+ if (btpan_cb.tap_fd >= 0)
+ {
+ btpan_cb.flow = 1;
+ conn->state = PAN_STATE_OPEN;
+ }
+ }
+}
+
+static void btpan_close_conn(btpan_conn_t* conn)
+{
+ BTIF_TRACE_API("btpan_close_conn: %p",conn);
+
+ if (conn && conn->state == PAN_STATE_OPEN)
+ {
+ BTIF_TRACE_DEBUG("btpan_close_conn: PAN_STATE_OPEN");
+
+ conn->state = PAN_STATE_CLOSE;
+ btpan_cb.open_count--;
+
+ if (btpan_cb.open_count == 0)
+ {
+ destroy_tap_read_thread();
+ if (btpan_cb.tap_fd != INVALID_FD)
+ {
+ btpan_tap_close(btpan_cb.tap_fd);
+ btpan_cb.tap_fd = INVALID_FD;
+ }
+ }
+ }
+}
+
+
static void btpan_cleanup_conn(btpan_conn_t* conn)
{
if (conn)
@@ -612,6 +668,7 @@ static void bta_pan_callback_transfer(UINT16 event, char *p_param)
{
state = BTPAN_STATE_CONNECTED;
status = BT_STATUS_SUCCESS;
+ btpan_open_conn(conn, p_data);
}
else
{
@@ -632,6 +689,7 @@ static void bta_pan_callback_transfer(UINT16 event, char *p_param)
btpan_conn_t* conn = btpan_find_conn_handle(p_data->close.handle);
LOG_INFO("%s: event = BTA_PAN_CLOSE_EVT handle %d", __FUNCTION__, p_data->close.handle);
+ btpan_close_conn(conn);
if (conn && conn->handle >= 0)
{