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

Commit 553e9d8d authored by Etienne Ruffieux's avatar Etienne Ruffieux Committed by Gerrit Code Review
Browse files

Merge changes from topic "bt_a2dp_src_sink_coexist"

* changes:
  Add A2DP src and sink co-exist feature bta layer (1/5)
  Add A2DP src and sink co-exist feature btif layer (2/5)
  Add A2DP src and sink co-exist feature stack layer (3/5)
  Add A2DP src and sink co-exist feature profile/avrcp layer (4/5)
  Add A2DP src and sink co-exist feature init::flag (5/5)
parents 17f791e6 87cb5b60
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ sysprop_library {
    name: "com.android.sysprop.bluetooth",
    host_supported: true,
    srcs: [
        "a2dp.sysprop",
        "avrcp.sysprop",
        "bta.sysprop",
        "hfp.sysprop",

sysprop/a2dp.sysprop

0 → 100644
+11 −0
Original line number Diff line number Diff line
module: "android.sysprop.bluetooth.A2dp"
owner: Platform

prop {
    api_name: "src_sink_coexist"
    type: Boolean
    scope: Internal
    access: Readonly
    prop_name: "bluetooth.a2dp.src_sink_coexist.enabled"
}
+105 −0
Original line number Diff line number Diff line
@@ -36,6 +36,35 @@ using namespace bluetooth::legacy::stack::sdp;
/* AV control block */
tBTA_AR_CB bta_ar_cb;

/*******************************************************************************
 *
 * Function         bta_ar_id
 *
 * Description      This function maps sys_id to ar id mask.
 *
 * Returns          void
 *
 ******************************************************************************/
static uint8_t bta_ar_id(tBTA_SYS_ID sys_id) {
  uint8_t mask = 0;
  if (sys_id == BTA_ID_AV) {
    mask = BTA_AR_AV_MASK;
  } else if (sys_id == BTA_ID_AVK) {
    mask = BTA_AR_AVK_MASK;
  }
  return mask;
}
static void bta_ar_avrc_add_cat(uint16_t categories) {
  uint8_t temp[sizeof(uint16_t)], *p;
  /* Change supported categories on the second one */
  if (bta_ar_cb.sdp_tg_handle != 0) {
    p = temp;
    UINT16_TO_BE_STREAM(p, categories);
    SDP_AddAttribute(bta_ar_cb.sdp_tg_handle, ATTR_ID_SUPPORTED_FEATURES,
                     UINT_DESC_TYPE, sizeof(temp), (uint8_t*)temp);
  }
}

/*******************************************************************************
 *
 * Function         bta_ar_init
@@ -246,3 +275,79 @@ void bta_ar_dereg_avrc(uint16_t service_uuid) {
    }
  }
}

/******************************************************************************
 *
 * Function         bta_ar_reg_avrc_for_src_sink_coexist
 *
 * Description      This function is called to register an SDP record for AVRCP.
 *                  Add sys_id to distinguish src or sink role and add also save
 *tg_categories
 *
 * Returns          void
 *
 *****************************************************************************/
void bta_ar_reg_avrc_for_src_sink_coexist(
    uint16_t service_uuid, const char* service_name, const char* provider_name,
    uint16_t categories, tBTA_SYS_ID sys_id, bool browse_supported,
    uint16_t profile_version) {
  uint8_t mask = bta_ar_id(sys_id);
  uint8_t temp[8], *p;
  uint16_t class_list[2];
  uint16_t count = 1;
  if (!mask || !categories) return;
  if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) {
    bta_ar_cb.tg_categories[mask - 1] = categories;
    categories = bta_ar_cb.tg_categories[0] | bta_ar_cb.tg_categories[1];
    if (bta_ar_cb.sdp_tg_handle == 0) {
      bta_ar_cb.tg_registered = mask;
      bta_ar_cb.sdp_tg_handle = SDP_CreateRecord();
      AVRC_AddRecord(service_uuid, service_name, provider_name, categories,
                     bta_ar_cb.sdp_tg_handle, browse_supported, profile_version,
                     0);
      bta_sys_add_uuid(service_uuid);
    }
    /* Change supported categories on the second one */
    bta_ar_avrc_add_cat(categories);
    /* only one TG is allowed (first-come, first-served).
     * If sdp_tg_handle is non-0, ignore this request */
  } else if ((service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) ||
             (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL)) {
    bta_ar_cb.ct_categories[mask - 1] = categories;
    categories = bta_ar_cb.ct_categories[0] | bta_ar_cb.ct_categories[1];
    if (bta_ar_cb.sdp_ct_handle == 0) {
      bta_ar_cb.sdp_ct_handle = SDP_CreateRecord();
      AVRC_AddRecord(service_uuid, service_name, provider_name, categories,
                     bta_ar_cb.sdp_ct_handle, browse_supported, profile_version,
                     0);
      bta_sys_add_uuid(service_uuid);
      bta_ar_cb.ct_ver = categories;
    } else {
      /* If first reg 1,3 version, reg 1.6 must update class id */
      if (bta_ar_cb.ct_ver < profile_version) {
        APPL_TRACE_API("%s ver=0x%x", __FUNCTION__, profile_version);
        if (bta_ar_cb.ct_ver <= AVRC_REV_1_3 &&
            profile_version > AVRC_REV_1_3) {
          bta_ar_cb.ct_ver = profile_version;
          /* add service class id list */
          class_list[0] = service_uuid;
          if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) {
            class_list[1] = UUID_SERVCLASS_AV_REM_CTRL_CONTROL;
            count = 2;
          }
          SDP_AddServiceClassIdList(bta_ar_cb.sdp_ct_handle, count, class_list);
        } else {
          bta_ar_cb.ct_ver = profile_version;
        }
        SDP_AddProfileDescriptorList(bta_ar_cb.sdp_ct_handle, service_uuid,
                                     profile_version);
      }
      /* multiple CT are allowed.
       * Change supported categories on the second one */
      p = temp;
      UINT16_TO_BE_STREAM(p, categories);
      SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES,
                       UINT_DESC_TYPE, (uint32_t)2, (uint8_t*)temp);
    }
  }
}
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ typedef struct {
  uint8_t tg_registered;
  tBTA_AV_HNDL hndl; /* Handle associated with the stream that rejected the
                        connection. */
  uint16_t ct_ver;
  uint16_t tg_categories[2];
} tBTA_AR_CB;

/*****************************************************************************
+103 −17
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "bta/include/bta_ar_api.h"
#include "bta/include/bta_av_co.h"
#include "btif/avrcp/avrcp_service.h"
#include "btif/include/btif_av.h"
#include "btif/include/btif_av_co.h"
#include "btif/include/btif_config.h"
#include "btif/include/btif_storage.h"
@@ -880,6 +881,7 @@ void bta_av_cleanup(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
  p_scb->wait = 0;
  p_scb->num_disc_snks = 0;
  p_scb->coll_mask = 0;
  p_scb->uuid_int = 0;
  alarm_cancel(p_scb->avrc_ct_timer);
  alarm_cancel(p_scb->link_signalling_timer);
  alarm_cancel(p_scb->accept_signalling_timer);
@@ -1038,7 +1040,9 @@ void bta_av_disconnect_req(tBTA_AV_SCB* p_scb,
  // the same index, it should be safe to use SCB index here.
  if ((bta_av_cb.conn_lcb & (1 << p_scb->hdi)) != 0) {
    p_rcb = bta_av_get_rcb_by_shdl((uint8_t)(p_scb->hdi + 1));
    if (p_rcb) bta_av_del_rc(p_rcb);
    if (p_rcb && p_scb->rc_handle != BTA_AV_RC_HANDLE_NONE) {
      bta_av_del_rc(p_rcb);
    }
    AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
  } else {
    APPL_TRACE_WARNING("%s: conn_lcb=0x%x bta_handle=0x%x (hdi=%u) no link",
@@ -1165,13 +1169,26 @@ void bta_av_setconfig_rsp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {

    /* only in case of local sep as SRC we need to look for other SEPs, In case
     * of SINK we don't */
    if (btif_av_src_sink_coexist_enabled()) {
      if (local_sep == AVDT_TSEP_SRC) {
        /* Make sure UUID has been initialized... */
      if (p_scb->uuid_int == 0) p_scb->uuid_int = p_scb->open_api.uuid;
        /* if local sep is source, uuid_int should be source */
        p_scb->uuid_int = UUID_SERVCLASS_AUDIO_SOURCE;
        bta_av_next_getcap(p_scb, p_data);
      } else {
        p_scb->uuid_int = UUID_SERVCLASS_AUDIO_SINK;
      }
    } else {
      if (local_sep == AVDT_TSEP_SRC) {
        /* Make sure UUID has been initialized... */
        if (p_scb->uuid_int == 0) {
          p_scb->uuid_int = p_scb->open_api.uuid;
        }
        bta_av_next_getcap(p_scb, p_data);
      }
    }
  }
}

/*******************************************************************************
 *
@@ -1446,6 +1463,33 @@ void bta_av_disc_results(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  /* store number of stream endpoints returned */
  p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;

  if (btif_av_src_sink_coexist_enabled()) {
    for (i = 0; i < p_scb->num_seps; i++) {
      /* steam not in use, is a sink, and is audio */
      if ((!p_scb->sep_info[i].in_use) &&
          (p_scb->sep_info[i].media_type == p_scb->media_type)) {
        if (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) num_snks++;

        if (p_scb->sep_info[i].tsep == AVDT_TSEP_SRC) num_srcs++;
      }
    }
    APPL_TRACE_DEBUG("both_enable=%d, uuid_int=0x%x, incoming=%d",
                     btif_av_both_enable(), uuid_int, p_scb->open_api.incoming);
    if (btif_av_both_enable() && p_scb->open_api.incoming) {
      if (uuid_int == UUID_SERVCLASS_AUDIO_SOURCE && num_snks == 0 &&
          num_srcs > 0) {
        p_scb->uuid_int = UUID_SERVCLASS_AUDIO_SINK;
        APPL_TRACE_DEBUG(" change UUID to 0x%x, num_snks=%u, num_srcs=%u",
                         p_scb->uuid_int, num_snks, num_srcs);
      } else if (uuid_int == UUID_SERVCLASS_AUDIO_SINK && num_srcs == 0 &&
                 num_snks > 0) {
        p_scb->uuid_int = UUID_SERVCLASS_AUDIO_SOURCE;
        APPL_TRACE_DEBUG(" change UUID to 0x%x, num_snks=%u, num_srcs=%u",
                         p_scb->uuid_int, num_snks, num_srcs);
      }
      uuid_int = p_scb->uuid_int;
    }
  } else {
    for (i = 0; i < p_scb->num_seps; i++) {
      /* steam not in use, is a sink, and is audio */
      if ((!p_scb->sep_info[i].in_use) &&
@@ -1459,6 +1503,7 @@ void bta_av_disc_results(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
          num_srcs++;
      }
    }
  }

  p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), p_scb->num_seps,
                         num_snks, num_srcs, uuid_int);
@@ -2373,7 +2418,7 @@ void bta_av_start_ok(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  {
    /* If sink starts stream, disable sniff mode here */
    if (!initiator) {
      /* If souce is the central role, disable role switch during streaming.
      /* If source is the central role, disable role switch during streaming.
       * Otherwise allow role switch, if source is peripheral.
       * Because it would not hurt source, if the peer device wants source to be
       * central.
@@ -3025,7 +3070,26 @@ void bta_av_open_rc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
      }
    } else {
      /* use main SM for AVRC SDP activities */
      if (is_new_avrcp_enabled()) {
      if (btif_av_both_enable()) {
        /* if peer is sink, it should run new avrcp */
        if ((p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC) &&
            is_new_avrcp_enabled()) {
          APPL_TRACE_WARNING("%s: local src Using the new AVRCP Profile",
                             __func__);
          if (bluetooth::avrcp::AvrcpService::Get() != nullptr) {
            bluetooth::avrcp::AvrcpService::Get()->ConnectDevice(
                p_scb->PeerAddress());
            return;
          }
        }

        APPL_TRACE_WARNING("%s: local sink Using the legacy AVRCP Profile",
                           __func__);
        bta_av_rc_disc((uint8_t)(p_scb->hdi + 1));

        return;
      }
      if (btif_av_is_source_enabled() && is_new_avrcp_enabled()) {
        APPL_TRACE_WARNING("%s: Using the new AVRCP Profile", __func__);
        bluetooth::avrcp::AvrcpService::Get()->ConnectDevice(
            p_scb->PeerAddress());
@@ -3343,3 +3407,25 @@ static void bta_av_offload_codec_builder(tBTA_AV_SCB* p_scb,
    APPL_TRACE_ERROR("%s: not a valid codec info", __func__);
  }
}
void bta_av_api_set_peer_sep(tBTA_AV_DATA* p_data) {
  APPL_TRACE_DEBUG("%s, bd_addr=%s, sep:%d", __func__,
                   ADDRESS_TO_LOGGABLE_CSTR(p_data->peer_sep.addr),
                   p_data->peer_sep.sep);
  const tBTA_AV_SCB* p_scb = bta_av_addr_to_scb(p_data->peer_sep.addr);
  if (!p_scb) {
    APPL_TRACE_WARNING("%s scb not found", __func__);
    return;
  }
  APPL_TRACE_DEBUG("%s, rc_handle:%d", __func__, p_scb->rc_handle);
  if (btif_av_both_enable()) {
    if (p_data->peer_sep.sep == AVDT_TSEP_SNK) {
      // src close legacy cback
      APPL_TRACE_WARNING("%s: current dut is src", __func__);
      AVRC_UpdateCcb(&p_data->peer_sep.addr, AVRC_CO_METADATA);
    } else if (p_data->peer_sep.sep == AVDT_TSEP_SRC) {
      // sink close new cback
      APPL_TRACE_WARNING("%s: current dut is sink", __func__);
      AVRC_UpdateCcb(&p_data->peer_sep.addr, AVRC_CO_GOOGLE);
    }
  }
}
Loading