OSDN Git Service

HFP-AG: Cleanup when incoming and outgoing connections collide.
authorSatish Kodishala <skodisha@codeaurora.org>
Mon, 16 Nov 2015 17:16:51 +0000 (22:46 +0530)
committerLinux Build Service Account <lnxbuild@localhost>
Wed, 24 Aug 2016 14:09:15 +0000 (08:09 -0600)
- When incoming and outgoing connections from/to same device collide,
  clean up outgoing path after incoming connection is accepted.

- Abort outgoing connection to the same device if collision is detected
  before making RFCOMM connection.

- Choose the connected device to send response for AT commands.

Change-Id: If5c86356ce0496ab63d6445257bdc1977d2cb56b

bta/ag/bta_ag_act.c
btif/src/btif_hf.c

index 3d52cef..29f7b27 100644 (file)
@@ -32,6 +32,7 @@
 #include <string.h>
 #include "bta_dm_int.h"
 #include "l2c_api.h"
+#include <cutils/properties.h>
 
 /*****************************************************************************
 **  Constants
@@ -200,6 +201,7 @@ void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 {
     BD_ADDR pending_bd_addr;
+    tBTA_AG_RFC     *p_buf;
 
     /* store parameters */
     if (p_data)
@@ -212,6 +214,26 @@ void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
     /* Check if RFCOMM has any incoming connection to avoid collision. */
     if (PORT_IsOpening (pending_bd_addr))
     {
+        char value[PROPERTY_VALUE_MAX];
+        if (property_get("persist.bt.max.hs.connections", value, "") &&
+                     !strcmp(value, "2") )
+        {
+            // Abort the outgoing connection if incoming connection is from the same device
+            if (bdcmp (pending_bd_addr, p_scb->peer_addr) == 0)
+            {
+                APPL_TRACE_WARNING("%s: p_scb %x, abort outgoing conn, there is"\
+                    " an incoming conn from dev %x:%x:%x:%x:%x:%x", __func__,
+                    p_scb, p_scb->peer_addr[0], p_scb->peer_addr[1],
+                    p_scb->peer_addr[2], p_scb->peer_addr[3], p_scb->peer_addr[4],
+                    p_scb->peer_addr[5]);
+                // send ourselves close event for clean up
+                p_buf = (tBTA_AG_RFC *) osi_malloc(sizeof(tBTA_AG_RFC));
+                p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
+                p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb);
+                bta_sys_sendmsg(p_buf);
+                return;
+            }
+        }
         /* Let the incoming connection goes through.                        */
         /* Issue collision for this scb for now.                            */
         /* We will decide what to do when we find incoming connetion later. */
@@ -552,6 +574,7 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
     tBTA_AG_SCB     *ag_scb, *other_scb;
     BD_ADDR         dev_addr;
     int             status;
+    tBTA_AG_RFC     *p_buf;
 
     /* set role */
     p_scb->role = BTA_AG_ACP;
@@ -574,8 +597,30 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 
             if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
             {
-                /* If incoming and outgoing device are same, nothing more to do.            */
-                /* Outgoing conn will be aborted because we have successful incoming conn.  */
+                char value[PROPERTY_VALUE_MAX];
+                /* Read the property if multi hf is enabled */
+                if (property_get("persist.bt.max.hs.connections", value, "") &&
+                     !strcmp(value, "2") )
+                {
+                    /* If incoming and outgoing device are same, nothing more to do.            */
+                    /* Outgoing conn will be aborted because we have successful incoming conn.  */
+                    APPL_TRACE_WARNING("%s: p_scb %x, abort outgoing conn,"\
+                      "there is an incoming conn from dev %x:%x:%x:%x:%x:%x",
+                      __func__, ag_scb, dev_addr[0], dev_addr[1], dev_addr[2],
+                      dev_addr[3], dev_addr[4], dev_addr[5]);
+                    if (ag_scb->conn_handle)
+                    {
+                        RFCOMM_RemoveConnection(ag_scb->conn_handle);
+                    }
+
+                    // send ourselves close event for clean up
+                    // move back to OPENING state from INIT state so that clean up is done
+                    ag_scb->state = 1;
+                    p_buf = (tBTA_AG_RFC *) osi_malloc(sizeof(tBTA_AG_RFC));
+                    p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
+                    p_buf->hdr.layer_specific = bta_ag_scb_to_idx(ag_scb);
+                    bta_sys_sendmsg(p_buf);
+                }
             }
             else
             {
index b3ee9c2..5475254 100644 (file)
@@ -222,7 +222,7 @@ static int btif_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
         int i;
         for (i = 0; i < btif_max_hf_clients; ++i)
         {
-            if ((bdcmp(bd_addr->address,
+            if (is_connected(bd_addr) && (bdcmp(bd_addr->address,
                                   btif_hf_cb[i].connected_bda.address) == 0))
                 return i;
         }
@@ -794,7 +794,7 @@ static bt_status_t disconnect( bt_bdaddr_t *bd_addr )
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         BTA_AgClose(btif_hf_cb[idx].handle);
         return BT_STATUS_SUCCESS;
@@ -828,7 +828,7 @@ static bt_status_t connect_audio( bt_bdaddr_t *bd_addr )
     if (btif_hf_check_if_slc_connected() != BT_STATUS_SUCCESS)
         return BT_STATUS_NOT_READY;
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         BTA_AgAudioOpen(btif_hf_cb[idx].handle);
 
@@ -862,7 +862,7 @@ static bt_status_t disconnect_audio( bt_bdaddr_t *bd_addr )
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         BTA_AgAudioClose(btif_hf_cb[idx].handle);
         return BT_STATUS_SUCCESS;
@@ -977,7 +977,7 @@ static bt_status_t volume_control(bthf_volume_type_t type, int volume,
 
     tBTA_AG_RES_DATA ag_res;
     memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         ag_res.num = volume;
         BTA_AgResult(btif_hf_cb[idx].handle,
@@ -1041,7 +1041,7 @@ static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         tBTA_AG_RES_DATA    ag_res;
 
@@ -1079,7 +1079,7 @@ static bt_status_t cind_response(int svc, int num_active, int num_held,
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         tBTA_AG_RES_DATA    ag_res;
 
@@ -1125,7 +1125,7 @@ static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         /* Format the response and send */
         memset (&ag_res, 0, sizeof (ag_res));
@@ -1160,7 +1160,7 @@ static bt_status_t at_response(bthf_at_response_t response_code,
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         send_at_result((response_code == BTHF_AT_RESPONSE_OK) ? BTA_AG_OK_DONE
                         : BTA_AG_OK_ERROR, error_code, idx);
@@ -1196,7 +1196,7 @@ static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
         return BT_STATUS_FAIL;
     }
 
-    if (is_connected(bd_addr) && (idx != BTIF_HF_INVALID_IDX))
+    if (idx != BTIF_HF_INVALID_IDX)
     {
         tBTA_AG_RES_DATA    ag_res;
         int                 xx;