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

Commit cd76f129 authored by Petri Gynther's avatar Petri Gynther Committed by Android (Google) Code Review
Browse files

Merge "A2DP Offload support" into pi-dev

parents 2d1c6f89 63183603
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -92,7 +92,9 @@ typedef enum {
  A2DP_CTRL_ACK_SUCCESS,
  A2DP_CTRL_ACK_FAILURE,
  A2DP_CTRL_ACK_INCALL_FAILURE, /* Failure when in Call*/
  A2DP_CTRL_ACK_UNSUPPORTED
  A2DP_CTRL_ACK_UNSUPPORTED,
  A2DP_CTRL_ACK_PENDING,
  A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS,
} tA2DP_CTRL_ACK;

typedef uint32_t tA2DP_SAMPLE_RATE;
+207 −65
Original line number Diff line number Diff line
@@ -32,11 +32,14 @@
#include <string.h>
#include <vector>

#include "a2dp_sbc.h"
#include "avdt_api.h"
#include "bt_utils.h"
#include "bta_av_int.h"
#include "btif/include/btif_av_co.h"
#include "btif/include/btif_storage.h"
#include "btm_int.h"
#include "device/include/controller.h"
#include "device/include/interop.h"
#include "l2c_api.h"
#include "l2cdefs.h"
@@ -44,10 +47,11 @@
#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "utl.h"

#if (BTA_AR_INCLUDED == TRUE)
#include "bta_ar_api.h"
#endif
#include "btif/include/btif_av.h"
#include "btif/include/btif_hf.h"

/*****************************************************************************
 *  Constants
@@ -73,6 +77,11 @@
/* ACL quota we are letting FW use for A2DP Offload Tx. */
#define BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA 4

#define MAX_2MBPS_AVDTP_MTU 663
#define BTIF_A2DP_MAX_BITPOOL_MQ 35

static void bta_av_offload_codec_builder(tBTA_AV_SCB* p_scb,
                                         tBT_A2DP_OFFLOAD* p_a2dp_offload);
static void bta_av_st_rc_timer(tBTA_AV_SCB* p_scb,
                               UNUSED_ATTR tBTA_AV_DATA* p_data);

@@ -97,7 +106,8 @@ const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos = {bta_av_co_audio_init,
                                           bta_av_co_audio_stop,
                                           bta_av_co_audio_source_data_path,
                                           bta_av_co_audio_delay,
                                           bta_av_co_audio_update_mtu};
                                           bta_av_co_audio_update_mtu,
                                           bta_av_co_content_protect_is_active};

/* ssm action functions for audio stream */
const tBTA_AV_SACT bta_av_a2dp_action[] = {
@@ -1844,9 +1854,10 @@ void bta_av_str_stopped(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  BT_HDR* p_buf;
  uint8_t policy = HCI_ENABLE_SNIFF_MODE;

  APPL_TRACE_ERROR("%s: peer %s handle:%d audio_open_cnt:%d, p_data %p",
                   __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
                   bta_av_cb.audio_open_cnt, p_data);
  APPL_TRACE_ERROR(
      "%s: peer %s handle:%d audio_open_cnt:%d, p_data %p start:%d", __func__,
      p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
      bta_av_cb.audio_open_cnt, p_data, start);

  bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
  if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
@@ -1855,17 +1866,10 @@ void bta_av_str_stopped(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);

  if (p_scb->co_started) {
    /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
    vendor_get_interface()->send_command(
        (vendor_opcode_t)BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
    if (p_scb->offload_start_pending) {
      tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
      tBTA_AV bta_av_data;
      bta_av_data.status = status;
      (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
    if (p_scb->offload_started) {
      bta_av_vendor_offload_stop();
      p_scb->offload_started = false;
    }
    p_scb->offload_start_pending = false;
    */

    bta_av_stream_chg(p_scb, false);
    p_scb->co_started = false;
@@ -2489,18 +2493,10 @@ void bta_av_suspend_cfm(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {

  /* in case that we received suspend_ind, we may need to call co_stop here */
  if (p_scb->co_started) {
    /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
    vendor_get_interface()->send_command(
        (vendor_opcode_t)BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
    if (p_scb->offload_start_pending) {
      tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
      tBTA_AV bta_av_data;
      bta_av_data.status = status;
      (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
    if (p_scb->offload_started) {
      bta_av_vendor_offload_stop();
      p_scb->offload_started = false;
    }
    p_scb->offload_start_pending = false;
    */

    bta_av_stream_chg(p_scb, false);

    {
@@ -2958,6 +2954,67 @@ void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  }
}

void offload_vendor_callback(tBTM_VSC_CMPL* param) {
  uint8_t status = 0;
  uint8_t sub_opcode = 0;
  if (param->param_len) {
    APPL_TRACE_DEBUG("%s: param_len = %d status = %d", __func__,
                     param->param_len, param->p_param_buf[0]);
    status = param->p_param_buf[0];
  }
  if (status == 0) {
    sub_opcode = param->p_param_buf[1];
    APPL_TRACE_DEBUG("%s: subopcode = %d", __func__, sub_opcode);
    switch (sub_opcode) {
      case VS_HCI_A2DP_OFFLOAD_STOP:
        APPL_TRACE_DEBUG("%s: VS_HCI_STOP_A2DP_MEDIA successful", __func__);
        break;
      case VS_HCI_A2DP_OFFLOAD_START:
        (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV*)&status);
        break;
      default:
        break;
    }
  } else {
    APPL_TRACE_DEBUG("%s: Offload failed for subopcode= %d", __func__,
                     sub_opcode);
    if (param->opcode != VS_HCI_A2DP_OFFLOAD_STOP)
      (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV*)&status);
  }
}

void bta_av_vendor_offload_start(tBTA_AV_SCB* p_scb,
                                 tBT_A2DP_OFFLOAD* offload_start) {
  uint8_t param[sizeof(tBT_A2DP_OFFLOAD)];
  APPL_TRACE_DEBUG("%s", __func__);

  uint8_t* p_param = param;
  *p_param++ = VS_HCI_A2DP_OFFLOAD_START;

  UINT32_TO_STREAM(p_param, offload_start->codec_type);
  UINT16_TO_STREAM(p_param, offload_start->max_latency);
  UINT16_TO_STREAM(p_param, offload_start->scms_t_enable);
  UINT32_TO_STREAM(p_param, offload_start->sample_rate);
  UINT8_TO_STREAM(p_param, offload_start->bits_per_sample);
  UINT8_TO_STREAM(p_param, offload_start->ch_mode);
  UINT32_TO_STREAM(p_param, offload_start->encoded_audio_bitrate);
  UINT16_TO_STREAM(p_param, offload_start->acl_hdl);
  UINT16_TO_STREAM(p_param, offload_start->l2c_rcid);
  UINT16_TO_STREAM(p_param, offload_start->mtu);
  ARRAY_TO_STREAM(p_param, offload_start->codec_info,
                  (int8_t)sizeof(offload_start->codec_info));
  p_scb->offload_started = true;
  BTM_VendorSpecificCommand(HCI_CONTROLLER_A2DP_OPCODE_OCF, p_param - param,
                            param, offload_vendor_callback);
}

void bta_av_vendor_offload_stop() {
  uint8_t param[sizeof(tBT_A2DP_OFFLOAD)];
  APPL_TRACE_DEBUG("%s", __func__);
  param[0] = VS_HCI_A2DP_OFFLOAD_STOP;
  BTM_VendorSpecificCommand(HCI_CONTROLLER_A2DP_OPCODE_OCF, 1, param,
                            offload_vendor_callback);
}
/*******************************************************************************
 *
 * Function         bta_av_offload_req
@@ -2971,16 +3028,24 @@ void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  tBTA_AV_STATUS status = BTA_AV_FAIL_RESOURCES;

  tBT_A2DP_OFFLOAD offload_start;
  APPL_TRACE_DEBUG("%s: stream %s, audio channels open %d", __func__,
                   p_scb->started ? "STARTED" : "STOPPED",
                   bta_av_cb.audio_open_cnt);

  /* Check if stream has already been started. */
  /* Support offload if only one audio source stream is open. */
  if (p_scb->started != true) {
    status = BTA_AV_FAIL_STREAM;
  } else {
    bta_av_offload_codec_builder(p_scb, &offload_start);
    bta_av_vendor_offload_start(p_scb, &offload_start);
    return;
  }
  if (status != BTA_AV_SUCCESS) {
    tBTA_AV bta_av_data;
    bta_av_data.status = status;
    (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
  }

  /* TODO(eisenbach): RE-IMPLEMENT USING VSC OR HAL EXTENSION
  uint16_t mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
  else if (bta_av_cb.audio_open_cnt == 1 &&
@@ -3018,11 +3083,6 @@ void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
    }
  }
 */
  if (status != BTA_AV_SUCCESS) {
    tBTA_AV bta_av_data;
    bta_av_data.status = status;
    (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
  }
}

/*******************************************************************************
@@ -3052,3 +3112,85 @@ void bta_av_offload_rsp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
  bta_av_data.status = status;
  (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, &bta_av_data);
}

static void bta_av_offload_codec_builder(tBTA_AV_SCB* p_scb,
                                         tBT_A2DP_OFFLOAD* p_a2dp_offload) {
  A2dpCodecConfig* CodecConfig = bta_av_get_a2dp_current_codec();
  btav_a2dp_codec_index_t codec_index =
      A2DP_SourceCodecIndex(p_scb->cfg.codec_info);
  uint32_t codec_type = 0;
  uint16_t mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
  if (mtu == 0 || mtu > p_scb->stream_mtu) mtu = p_scb->stream_mtu;
  APPL_TRACE_DEBUG("%s:codec_index = %d", __func__, codec_index);
  switch (codec_index) {
    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
      codec_type = BTA_AV_CODEC_TYPE_SBC;
      if (A2DP_GetMaxBitpoolSbc(p_scb->cfg.codec_info) <=
          BTIF_A2DP_MAX_BITPOOL_MQ) {
        APPL_TRACE_WARNING("%s: Restricting streaming MTU size for MQ Bitpool",
                           __func__);
        mtu = MAX_2MBPS_AVDTP_MTU;
      }
      break;
    case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
      codec_type = BTA_AV_CODEC_TYPE_AAC;
      break;
    case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
      codec_type = BTA_AV_CODEC_TYPE_APTX;
      break;
    case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
      codec_type = BTA_AV_CODEC_TYPE_APTXHD;
      break;
    case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
      codec_type = BTA_AV_CODEC_TYPE_LDAC;
      break;
    default:
      APPL_TRACE_ERROR("%s: Unknown Codec type ", __func__);
      return;
  }
  if (mtu > BTA_AV_MAX_A2DP_MTU) mtu = BTA_AV_MAX_A2DP_MTU;
  p_a2dp_offload->codec_type = codec_type;
  p_a2dp_offload->max_latency = 0;
  p_a2dp_offload->mtu = mtu;
  p_a2dp_offload->acl_hdl =
      BTM_GetHCIConnHandle(p_scb->peer_addr, BT_TRANSPORT_BR_EDR);
  p_a2dp_offload->scms_t_enable = p_scb->p_cos->cp_is_active(p_scb->peer_addr);
  APPL_TRACE_DEBUG("%s: scms_t_enable =%d", __func__,
                   p_a2dp_offload->scms_t_enable);

  switch (A2DP_GetTrackSampleRate(p_scb->cfg.codec_info)) {
    case 44100:
      p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
      break;
    case 48000:
      p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
      break;
    case 88200:
      p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
      break;
    case 96000:
      p_a2dp_offload->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
      break;
  }
  if (L2CA_GetIdentifiers(p_scb->l2c_cid, &p_a2dp_offload->l2c_rcid, NULL) ==
      false) {
    APPL_TRACE_ERROR("%s: Failed to fetch l2c rcid", __func__);
    return;
  }
  switch (CodecConfig->getAudioBitsPerSample()) {
    case 16:
      p_a2dp_offload->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
      break;
    case 24:
      p_a2dp_offload->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24;
      break;
    case 32:
      p_a2dp_offload->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
      break;
  }
  p_a2dp_offload->ch_mode = A2DP_GetTrackChannelCount(p_scb->cfg.codec_info);
  p_a2dp_offload->encoded_audio_bitrate = CodecConfig->getTrackBitRate();
  if (!CodecConfig->getCodecSpecificConfig(p_a2dp_offload)) {
    APPL_TRACE_ERROR("%s: not a valid codec info", __func__);
  }
}
+27 −0
Original line number Diff line number Diff line
@@ -191,6 +191,9 @@ typedef void (*tBTA_AV_CO_UPDATE_MTU)(tBTA_AV_HNDL bta_av_handle,
                                      const RawAddress& peer_addr,
                                      uint16_t mtu);

typedef bool (*tBTA_AV_CO_CONTENT_PROTECT_IS_ACTIVE)(
    const RawAddress& peer_addr);

/* the call-out functions for one stream */
typedef struct {
  tBTA_AV_CO_INIT init;
@@ -204,6 +207,7 @@ typedef struct {
  tBTA_AV_CO_DATAPATH data;
  tBTA_AV_CO_DELAY delay;
  tBTA_AV_CO_UPDATE_MTU update_mtu;
  tBTA_AV_CO_CONTENT_PROTECT_IS_ACTIVE cp_is_active;
} tBTA_AV_CO_FUNCTS;

/* data type for BTA_AV_API_ENABLE_EVT */
@@ -511,6 +515,7 @@ struct tBTA_AV_SCB {
  uint16_t uuid_int; /*intended UUID of Initiator to connect to */
  bool offload_start_pending;
  bool skip_sdp; /* Decides if sdp to be done prior to profile connection */
  bool offload_started;
};

#define BTA_AV_RC_ROLE_MASK 0x10
@@ -572,6 +577,27 @@ typedef struct {
  uint8_t audio_streams; /* handle mask of streaming audio channels */
} tBTA_AV_CB;

// A2DP offload VSC parameters
class tBT_A2DP_OFFLOAD {
 public:
  uint32_t codec_type;            /* codec types ex: SBC/AAC/LDAC/APTx */
  uint16_t max_latency;           /* maximum latency */
  uint16_t scms_t_enable;         /* content protection enable */
  uint32_t sample_rate;           /* Sample rates ex: 44.1/48/88.2/96 Khz */
  uint8_t bits_per_sample;        /* bits per sample ex: 16/24/32 */
  uint8_t ch_mode;                /* None:0 Left:1 Right:2 */
  uint32_t encoded_audio_bitrate; /* encoder audio bitrates */
  uint16_t acl_hdl;               /* connection handle */
  uint16_t l2c_rcid;              /* l2cap channel id */
  uint16_t mtu;                   /* MTU size */
  uint8_t codec_info[32];         /* Codec specific information */
};

/* Vendor OFFLOAD VSC */
#define HCI_VSQC_CONTROLLER_A2DP_OPCODE 0x000A

#define VS_HCI_A2DP_OFFLOAD_START 0x01
#define VS_HCI_A2DP_OFFLOAD_STOP 0x02
/*****************************************************************************
 *  Global data
 ****************************************************************************/
@@ -711,5 +737,6 @@ extern void bta_av_delay_co(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_offload_req(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_offload_rsp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_vendor_offload_stop(void);

#endif /* BTA_AV_INT_H */
+9 −0
Original line number Diff line number Diff line
@@ -154,6 +154,15 @@ typedef uint8_t tBTA_AV_ERR;

typedef uint8_t tBTA_AV_EVT;

typedef enum {
  BTA_AV_CODEC_TYPE_UNKNOWN = 0x00,
  BTA_AV_CODEC_TYPE_SBC = 0x01,
  BTA_AV_CODEC_TYPE_AAC = 0x02,
  BTA_AV_CODEC_TYPE_APTX = 0x04,
  BTA_AV_CODEC_TYPE_APTXHD = 0x08,
  BTA_AV_CODEC_TYPE_LDAC = 0x10
} tBTA_AV_CODEC_TYPE;

/* Event associated with BTA_AV_ENABLE_EVT */
typedef struct { tBTA_AV_FEAT features; } tBTA_AV_ENABLE;

+11 −0
Original line number Diff line number Diff line
@@ -224,4 +224,15 @@ void bta_av_co_audio_delay(tBTA_AV_HNDL bta_av_handle,
void bta_av_co_audio_update_mtu(tBTA_AV_HNDL bta_av_handle,
                                const RawAddress& peer_address, uint16_t mtu);

/*******************************************************************************
 **
 ** Function         bta_av_co_content_protect_is_active
 **
 ** Description     Get the current configuration of content protection
 **
 ** Returns          TRUE if the current streaming has CP, FALSE otherwise
 **
 ******************************************************************************/
bool bta_av_co_content_protect_is_active(const RawAddress& peer_address);

#endif /* BTA_AV_CO_H */
Loading