Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8474c598 authored by jinyao.yu's avatar jinyao.yu Committed by jinyao yu
Browse files

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
parent 112fe86b
Loading
Loading
Loading
Loading
+23 −11
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@
 *****************************************************************************/

#define LOG_TAG "bluetooth"

#ifdef __ANDROID__
#include <a2dp.sysprop.h>
#endif
#include <string.h>

#include "avct_api.h"
@@ -545,6 +547,15 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
    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);
@@ -556,6 +567,7 @@ void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
                               p_data->p_buf);
      return;
    }
  }

  /* PID not found; drop message */
  AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
+7 −3
Original line number Diff line number Diff line
@@ -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
 ****************************************************************************/
+18 −2
Original line number Diff line number Diff line
@@ -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;

+127 −29
Original line number Diff line number Diff line
@@ -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,6 +228,59 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
  int i;
  bool bind = false;

#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);
          }
        }
      }
    }
  } else
#endif
  {
    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
      /* if ccb allocated and */
      if (p_ccb->allocated) {
@@ -233,18 +288,20 @@ void avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
        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);
          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 */
        /* 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);
          p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
                                 0, &p_lcb->peer_addr);
        }
      }
    }
  }
@@ -626,6 +683,15 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
    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);
@@ -637,6 +703,7 @@ void avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
                               p_data->p_buf);
      return;
    }
  }

  /* PID not found; drop message */
  AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
@@ -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;
}
+18 −3
Original line number Diff line number Diff line
@@ -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);
    }
  }
}
Loading