Fix PAN and AV role switch war
Bug: 23740164
Change-Id: Ib26a64b624c711443201adc4fde6b041ecb0dde1
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index eb49637..5230d8f 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -3689,7 +3689,8 @@
versions are stored in a blacklist and role switch with these devices are
delayed to avoid the collision with link encryption setup */
- if (delay_role_switch == FALSE)
+ if (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_SLAVE_ROLE_ONLY &&
+ delay_role_switch == FALSE)
{
BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
HCI_ROLE_MASTER, NULL);
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index 014c431..744a6fc 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -86,7 +86,11 @@
#define BTA_AV_ROLE BTA_MASTER_ROLE_PREF
#endif
-#define BTA_DM_NUM_RM_ENTRY 4
+#ifndef BTA_PANU_ROLE
+/* By default, AV role (backward BTA_MASTER_ROLE_PREF) */
+#define BTA_PANU_ROLE BTA_SLAVE_ROLE_ONLY
+#endif
+#define BTA_DM_NUM_RM_ENTRY 6
/* appids for PAN used by insight sample application
these have to be same as defined in btui_int.h */
@@ -100,8 +104,10 @@
const tBTA_DM_RM bta_dm_rm_cfg[] =
{
{BTA_ID_SYS, BTA_DM_NUM_RM_ENTRY, BTA_DM_SCATTERNET},
- {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_MASTER_ROLE_ONLY},
- {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_MASTER_ROLE_ONLY},
+ {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_ANY_ROLE},
+ {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_ANY_ROLE},
+ {BTA_ID_PAN, BTA_APP_ID_PAN_MULTI, BTA_MASTER_ROLE_ONLY},
+ {BTA_ID_PAN, BTUI_PAN_ID_PANU, BTA_PANU_ROLE},
{BTA_ID_HH, BTA_ALL_APP_ID, BTA_HH_ROLE},
{BTA_ID_AV, BTA_ALL_APP_ID, BTA_AV_ROLE}
};
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index a470d1a..648d118 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -181,6 +181,7 @@
/* Ignore for Discoverable, Connectable only for LE modes */
#define BTA_DM_LE_IGNORE 0xFF00
+#define BTA_APP_ID_PAN_MULTI 0xFE /* app id for pan multiple connection */
#define BTA_ALL_APP_ID 0xFF
/* Discoverable Modes */
@@ -248,6 +249,7 @@
#define BTA_ANY_ROLE 0x00
#define BTA_MASTER_ROLE_PREF 0x01
#define BTA_MASTER_ROLE_ONLY 0x02
+#define BTA_SLAVE_ROLE_ONLY 0x03 /* Used for PANU only, skip role switch to master */
typedef UINT8 tBTA_PREF_ROLES;
diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c
index ef7bee7..d4bd1c1 100644
--- a/bta/pan/bta_pan_act.c
+++ b/bta/pan/bta_pan_act.c
@@ -295,6 +295,53 @@
/*******************************************************************************
**
+** Function bta_pan_has_multiple_connections
+**
+** Description Check whether there are multiple GN/NAP connections to
+** different devices
+**
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+static BOOLEAN bta_pan_has_multiple_connections(UINT8 app_id)
+{
+ tBTA_PAN_SCB *p_scb = NULL;
+ BOOLEAN found = FALSE;
+ BD_ADDR bd_addr;
+
+ for (UINT8 index = 0; index < BTA_PAN_NUM_CONN; index++)
+ {
+ p_scb = &bta_pan_cb.scb[index];
+ if (p_scb->in_use == TRUE && app_id == p_scb->app_id)
+ {
+ /* save temp bd_addr */
+ bdcpy(bd_addr, p_scb->bd_addr);
+ found = TRUE;
+ break;
+ }
+ }
+
+ /* If cannot find a match then there is no connection at all */
+ if (found == FALSE)
+ return FALSE;
+
+ /* Find whether there is another connection with different device other than PANU.
+ Could be same service or different service */
+ for (UINT8 index = 0; index < BTA_PAN_NUM_CONN; index++)
+ {
+ p_scb = &bta_pan_cb.scb[index];
+ if (p_scb->in_use == TRUE && p_scb->app_id != bta_pan_cb.app_id[0] &&
+ bdcmp(bd_addr, p_scb->bd_addr))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*******************************************************************************
+**
** Function bta_pan_enable
**
** Description
@@ -565,6 +612,18 @@
data.status = BTA_PAN_FAIL;
}
+ p_scb->pan_flow_enable = TRUE;
+ p_scb->app_flow_enable = TRUE;
+
+ /* If app_id is NAP/GN, check whether there are multiple connections.
+ If there are, provide a special app_id to dm to enforce master role only. */
+ if ((p_scb->app_id == bta_pan_cb.app_id[1] || p_scb->app_id == bta_pan_cb.app_id[2]) &&
+ bta_pan_has_multiple_connections(p_scb->app_id))
+ {
+ p_scb->app_id = BTA_APP_ID_PAN_MULTI;
+ }
+
+ bta_sys_conn_open(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr);
bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);