diff options
| author | 2022-12-20 13:35:22 +0800 | |
|---|---|---|
| committer | 2023-06-08 22:43:47 +0000 | |
| commit | 8474c5984461a4db33eca4859a2587161aeafbea (patch) | |
| tree | bae26e6682d982b05dd2a87a249b9eda2b240f37 | |
| parent | 112fe86b9c34c7c82c84b2d24fc81f400576c443 (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.cc | 34 | ||||
| -rw-r--r-- | system/stack/avct/avct_int.h | 10 | ||||
| -rw-r--r-- | system/stack/avct/avct_l2c.cc | 20 | ||||
| -rw-r--r-- | system/stack/avct/avct_lcb_act.cc | 156 | ||||
| -rw-r--r-- | system/stack/avrc/avrc_api.cc | 21 | ||||
| -rw-r--r-- | system/stack/include/avrc_api.h | 14 |
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 */ |