summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author jinyao.yu <jinyao.yu@mediatek.com> 2022-12-20 13:35:22 +0800
committer jinyao yu <jinyao.yu@mediatek.com> 2023-06-08 22:43:47 +0000
commit8474c5984461a4db33eca4859a2587161aeafbea (patch)
treebae26e6682d982b05dd2a87a249b9eda2b240f37
parent112fe86b9c34c7c82c84b2d24fc81f400576c443 (diff)
Add A2DP src and sink co-exist feature stack layer (3/5)
[Description] Add A2DP src and sink co-exist feature, that we can connect both sink and src remote device at the same time while only keep 1 streaming. Bug: 256938279 Test: A2DP src/sink connect, streaming successully, net_test_btif_rc unit test pass Change-Id: I89ee7391253daffa8992a5e1fafba38635414641
-rw-r--r--system/stack/avct/avct_bcb_act.cc34
-rw-r--r--system/stack/avct/avct_int.h10
-rw-r--r--system/stack/avct/avct_l2c.cc20
-rw-r--r--system/stack/avct/avct_lcb_act.cc156
-rw-r--r--system/stack/avrc/avrc_api.cc21
-rw-r--r--system/stack/include/avrc_api.h14
6 files changed, 201 insertions, 54 deletions
diff --git a/system/stack/avct/avct_bcb_act.cc b/system/stack/avct/avct_bcb_act.cc
index 2503d81562..cfbaf7655f 100644
--- a/system/stack/avct/avct_bcb_act.cc
+++ b/system/stack/avct/avct_bcb_act.cc
@@ -26,7 +26,9 @@
*****************************************************************************/
#define LOG_TAG "bluetooth"
-
+#ifdef __ANDROID__
+#include <a2dp.sysprop.h>
+#endif
#include <string.h>
#include "avct_api.h"
@@ -545,16 +547,26 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
return;
}
- /* parse and lookup PID */
- BE_STREAM_TO_UINT16(pid, p);
- p_ccb = avct_lcb_has_pid(p_lcb, pid);
- if (p_ccb) {
- /* PID found; send msg up, adjust bt hdr and call msg callback */
- p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
- p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
- (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
- p_data->p_buf);
- return;
+#ifdef OS_ANDROID
+ bool bind = false;
+ if (android::sysprop::bluetooth::A2dp::src_sink_coexist().value_or(false)) {
+ bind = avct_msg_ind_for_src_sink_coexist(p_lcb, p_data, label, cr_ipid);
+ osi_free_and_reset((void**)&p_data->p_buf);
+ if (bind) return;
+ } else
+#endif
+ {
+ /* parse and lookup PID */
+ BE_STREAM_TO_UINT16(pid, p);
+ p_ccb = avct_lcb_has_pid(p_lcb, pid);
+ if (p_ccb) {
+ /* PID found; send msg up, adjust bt hdr and call msg callback */
+ p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
+ p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
+ (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
+ p_data->p_buf);
+ return;
+ }
}
/* PID not found; drop message */
diff --git a/system/stack/avct/avct_int.h b/system/stack/avct/avct_int.h
index 3139dbce3a..25e682c257 100644
--- a/system/stack/avct/avct_int.h
+++ b/system/stack/avct/avct_int.h
@@ -92,9 +92,9 @@ typedef struct {
uint8_t allocated; /* 0, not allocated. index+1, otherwise. */
uint8_t state; /* The state machine state */
uint8_t ch_state; /* L2CAP channel state */
- BT_HDR* p_tx_msg; /* Message to be sent - in case the browsing channel is not
- open when MsgReg is called */
- uint8_t ch_close; /* CCB index+1, if CCB initiated channel close */
+ BT_HDR* p_tx_msg; /* Message to be sent - in case the browsing channel is not
+ open when MsgReg is called */
+ uint8_t ch_close; /* CCB index+1, if CCB initiated channel close */
RawAddress peer_addr; /* BD address of peer */
} tAVCT_BCB;
@@ -201,6 +201,10 @@ void avct_ccb_dealloc(tAVCT_CCB* p_ccb, uint8_t event, uint16_t result,
uint8_t avct_ccb_to_idx(tAVCT_CCB* p_ccb);
tAVCT_CCB* avct_ccb_by_idx(uint8_t idx);
+extern bool avct_msg_ind_for_src_sink_coexist(tAVCT_LCB* p_lcb,
+ tAVCT_LCB_EVT* p_data,
+ uint8_t label, uint8_t cr_ipid);
+
/*****************************************************************************
* global data
****************************************************************************/
diff --git a/system/stack/avct/avct_l2c.cc b/system/stack/avct/avct_l2c.cc
index 7634a65653..7e83940af7 100644
--- a/system/stack/avct/avct_l2c.cc
+++ b/system/stack/avct/avct_l2c.cc
@@ -21,6 +21,10 @@
* This AVCTP module interfaces to L2CAP
*
******************************************************************************/
+#ifdef __ANDROID__
+#include <a2dp.sysprop.h>
+#endif
+#include <base/logging.h>
#include "avct_api.h"
#include "avct_int.h"
@@ -32,8 +36,6 @@
#include "stack/include/bt_hdr.h"
#include "types/raw_address.h"
-#include <base/logging.h>
-
/* callback function declarations */
void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
uint16_t psm, uint8_t id);
@@ -142,6 +144,20 @@ void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
/* if result ok, proceed with connection */
if (result == L2CAP_CONN_OK) {
+#ifdef OS_ANDROID
+ if (android::sysprop::bluetooth::A2dp::src_sink_coexist().value_or(false)) {
+ tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
+ for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
+ if (p_ccb && p_ccb->allocated && (p_ccb->p_lcb == NULL) &&
+ (p_ccb->cc.role == AVCT_ACP)) {
+ p_ccb->p_lcb = p_lcb;
+ AVCT_TRACE_DEBUG(
+ "ACP bind %d ccb to lcb, alloc %d, lcb %p, role %d, pid 0x%x", i,
+ p_ccb->allocated, p_ccb->p_lcb, p_ccb->cc.role, p_ccb->cc.pid);
+ }
+ }
+ }
+#endif
/* store LCID */
p_lcb->ch_lcid = lcid;
diff --git a/system/stack/avct/avct_lcb_act.cc b/system/stack/avct/avct_lcb_act.cc
index 99f1d6b969..0ba04443d7 100644
--- a/system/stack/avct/avct_lcb_act.cc
+++ b/system/stack/avct/avct_lcb_act.cc
@@ -21,7 +21,9 @@
* This module contains action functions of the link control state machine.
*
******************************************************************************/
-
+#ifdef __ANDROID__
+#include <a2dp.sysprop.h>
+#endif
#include <string.h>
#include "avct_api.h"
@@ -226,25 +228,80 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
int i;
bool bind = false;
- for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
- /* if ccb allocated and */
- if (p_ccb->allocated) {
- /* if bound to this lcb send connect confirm event */
- if (p_ccb->p_lcb == p_lcb) {
- bind = true;
- L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
- p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT, 0,
- &p_lcb->peer_addr);
+#ifdef OS_ANDROID
+ if (android::sysprop::bluetooth::A2dp::src_sink_coexist().value_or(false)) {
+ bool is_originater = false;
+
+ for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
+ if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) &&
+ p_ccb->cc.role == AVCT_INT) {
+ AVCT_TRACE_DEBUG("%s, find int handle %d", __func__, i);
+ is_originater = true;
+ }
+ }
+
+ p_ccb = &avct_cb.ccb[0];
+ for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
+ /* if ccb allocated and */
+ /** M: to avoid avctp collision, make sure the collision can be checked @{
+ */
+ AVCT_TRACE_DEBUG("%s, %d ccb to lcb, alloc %d, lcb %p, role %d, pid 0x%x",
+ __func__, i, p_ccb->allocated, p_ccb->p_lcb,
+ p_ccb->cc.role, p_ccb->cc.pid);
+ if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
+ /* if bound to this lcb send connect confirm event */
+ if (p_ccb->cc.role == AVCT_INT) {
+ /** @} */
+ bind = true;
+ L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
+ p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
+ 0, &p_lcb->peer_addr);
+ }
+ /* if unbound acceptor and lcb doesn't already have a ccb for this PID
+ */
+ /** M: to avoid avctp collision, make sure the collision can be checked
+ @{ */
+ else if ((p_ccb->cc.role == AVCT_ACP) &&
+ avct_lcb_has_pid(p_lcb, p_ccb->cc.pid)) {
+ /* bind ccb to lcb and send connect ind event */
+ if (is_originater) {
+ AVCT_TRACE_ERROR("%s, int exist, unbind acp handle:%d", __func__,
+ i);
+ p_ccb->p_lcb = NULL;
+ } else {
+ bind = true;
+ p_ccb->p_lcb = p_lcb;
+ L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
+ p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
+ 0, &p_lcb->peer_addr);
+ }
+ }
}
- /* if unbound acceptor and lcb doesn't already have a ccb for this PID */
- else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
- (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL)) {
- /* bind ccb to lcb and send connect ind event */
- bind = true;
- p_ccb->p_lcb = p_lcb;
- L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
- p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT, 0,
- &p_lcb->peer_addr);
+ }
+ } else
+#endif
+ {
+ for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
+ /* if ccb allocated and */
+ if (p_ccb->allocated) {
+ /* if bound to this lcb send connect confirm event */
+ if (p_ccb->p_lcb == p_lcb) {
+ bind = true;
+ L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
+ p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
+ 0, &p_lcb->peer_addr);
+ }
+ /* if unbound acceptor and lcb doesn't already have a ccb for this PID
+ */
+ else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
+ (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL)) {
+ /* bind ccb to lcb and send connect ind event */
+ bind = true;
+ p_ccb->p_lcb = p_lcb;
+ L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
+ p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
+ 0, &p_lcb->peer_addr);
+ }
}
}
}
@@ -626,16 +683,26 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
return;
}
- /* parse and lookup PID */
- BE_STREAM_TO_UINT16(pid, p);
- p_ccb = avct_lcb_has_pid(p_lcb, pid);
- if (p_ccb) {
- /* PID found; send msg up, adjust bt hdr and call msg callback */
- p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
- p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
- (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
- p_data->p_buf);
- return;
+#ifdef OS_ANDROID
+ bool bind = false;
+ if (android::sysprop::bluetooth::A2dp::src_sink_coexist().value_or(false)) {
+ bind = avct_msg_ind_for_src_sink_coexist(p_lcb, p_data, label, cr_ipid);
+ osi_free_and_reset((void**)&p_data->p_buf);
+ if (bind) return;
+ } else
+#endif
+ {
+ /* parse and lookup PID */
+ BE_STREAM_TO_UINT16(pid, p);
+ p_ccb = avct_lcb_has_pid(p_lcb, pid);
+ if (p_ccb) {
+ /* PID found; send msg up, adjust bt hdr and call msg callback */
+ p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
+ p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
+ (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
+ p_data->p_buf);
+ return;
+ }
}
/* PID not found; drop message */
@@ -653,3 +720,34 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
}
}
+
+bool avct_msg_ind_for_src_sink_coexist(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data,
+ uint8_t label, uint8_t cr_ipid) {
+ bool bind = false;
+ tAVCT_CCB* p_ccb;
+ int p_buf_len;
+ uint8_t* p;
+ uint16_t pid;
+
+ p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset;
+
+ BE_STREAM_TO_UINT16(pid, p);
+
+ p_ccb = &avct_cb.ccb[0];
+ p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
+ p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
+ p_buf_len = BT_HDR_SIZE + p_data->p_buf->offset + p_data->p_buf->len;
+
+ for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
+ if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb->cc.pid == pid)) {
+ /* PID found; send msg up, adjust bt hdr and call msg callback */
+ bind = true;
+ BT_HDR* p_tmp_buf = (BT_HDR*)osi_malloc(p_buf_len);
+ memcpy(p_tmp_buf, p_data->p_buf, p_buf_len);
+ (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
+ p_tmp_buf);
+ }
+ }
+
+ return bind;
+}
diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc
index fff1b150d8..f97a14f12c 100644
--- a/system/stack/avrc/avrc_api.cc
+++ b/system/stack/avrc/avrc_api.cc
@@ -24,6 +24,7 @@
#include "avrc_api.h"
#ifdef __ANDROID__
+#include <a2dp.sysprop.h>
#include <avrcp.sysprop.h>
#endif
#include <base/logging.h>
@@ -626,7 +627,7 @@ static uint8_t avrc_proc_far_msg(uint8_t handle, uint8_t label, uint8_t cr,
avrc_command.continu = avrc_cmd;
status = AVRC_BldCommand(&avrc_command, &p_cmd);
if (status == AVRC_STS_NO_ERROR) {
- AVRC_MsgReq(handle, (uint8_t)(label), AVRC_CMD_CTRL, p_cmd);
+ AVRC_MsgReq(handle, (uint8_t)(label), AVRC_CMD_CTRL, p_cmd, false);
}
}
@@ -1179,8 +1180,9 @@ uint16_t AVRC_CloseBrowse(uint8_t handle) { return AVCT_RemoveBrowse(handle); }
* AVRC_BAD_HANDLE if handle is invalid.
*
*****************************************************************************/
+/* legacy and new avrcp send the different packet format for VENDOR op */
uint16_t AVRC_MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
- BT_HDR* p_pkt) {
+ BT_HDR* p_pkt, bool is_new_avrcp) {
uint8_t* p_data;
uint8_t cr = AVCT_CMD;
bool chk_frag = true;
@@ -1196,7 +1198,11 @@ uint16_t AVRC_MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
AVRC_TRACE_DEBUG("%s handle = %u label = %u ctype = %u len = %d", __func__,
handle, label, ctype, p_pkt->len);
/* Handle for AVRCP fragment */
- bool is_new_avrcp = osi_property_get_bool("bluetooth.profile.avrcp.target.enabled", false);
+#ifdef OS_ANDROID
+ if (!android::sysprop::bluetooth::A2dp::src_sink_coexist().value_or(false))
+#endif
+ is_new_avrcp =
+ osi_property_get_bool("bluetooth.profile.avrcp.target.enabled", false);
if (ctype >= AVRC_RSP_NOT_IMPL) cr = AVCT_RSP;
if (p_pkt->event == AVRC_OP_VENDOR) {
@@ -1455,3 +1461,12 @@ void AVRC_SaveControllerVersion(const RawAddress& bdaddr,
ADDRESS_TO_LOGGABLE_CSTR(bdaddr));
}
}
+
+void AVRC_UpdateCcb(RawAddress* addr, uint32_t company_id) {
+ for (uint8_t i = 0; i < AVCT_NUM_CONN; i++) {
+ LOG_INFO("%s: handle:%d, update cback:0x%0x", __func__, i, company_id);
+ if (avrc_cb.ccb[i].company_id == company_id) {
+ avrc_cb.ccb[i].ctrl_cback.Run(i, AVRC_CLOSE_IND_EVT, 0, addr);
+ }
+ }
+}
diff --git a/system/stack/include/avrc_api.h b/system/stack/include/avrc_api.h
index 8f5d9dd114..247840bead 100644
--- a/system/stack/include/avrc_api.h
+++ b/system/stack/include/avrc_api.h
@@ -237,11 +237,11 @@ using tAVRC_MSG_CBACK = base::Callback<void(uint8_t handle, uint8_t label,
uint8_t opcode, tAVRC_MSG* p_msg)>;
typedef struct {
- tAVRC_CTRL_CBACK ctrl_cback; /* application control callback */
- tAVRC_MSG_CBACK msg_cback; /* application message callback */
- uint32_t company_id; /* the company ID */
- uint8_t conn; /* Connection role (Initiator/acceptor) */
- uint8_t control; /* Control role (Control/Target) */
+ tAVRC_CTRL_CBACK ctrl_cback; /* application control callback */
+ tAVRC_MSG_CBACK msg_cback; /* application message callback */
+ uint32_t company_id; /* the company ID */
+ uint8_t conn; /* Connection role (Initiator/acceptor) */
+ uint8_t control; /* Control role (Control/Target) */
} tAVRC_CONN_CB;
typedef struct {
@@ -510,7 +510,7 @@ uint16_t AVRC_CloseBrowse(uint8_t handle);
*
*****************************************************************************/
uint16_t AVRC_MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
- BT_HDR* p_pkt);
+ BT_HDR* p_pkt, bool is_new_avrcp);
/******************************************************************************
*
@@ -833,4 +833,6 @@ bool AVRC_IsValidAvcType(uint8_t pdu_id, uint8_t avc_type);
******************************************************************************/
bool AVRC_IsValidPlayerAttr(uint8_t attr);
+void AVRC_UpdateCcb(RawAddress* addr, uint32_t company_id);
+
#endif /* AVRC_API_H */