Loading system/audio_a2dp_hw/include/audio_a2dp_hw.h +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading system/bta/av/bta_av_aact.cc +207 −65 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 Loading @@ -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); Loading @@ -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[] = { Loading Loading @@ -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 || Loading @@ -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; Loading Loading @@ -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); { Loading Loading @@ -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 Loading @@ -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 && Loading Loading @@ -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); } } /******************************************************************************* Loading Loading @@ -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__); } } system/bta/av/bta_av_int.h +27 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 */ Loading Loading @@ -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 Loading Loading @@ -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 ****************************************************************************/ Loading Loading @@ -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 */ system/bta/include/bta_av_api.h +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading system/bta/include/bta_av_co.h +11 −0 Original line number Diff line number Diff line Loading @@ -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
system/audio_a2dp_hw/include/audio_a2dp_hw.h +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
system/bta/av/bta_av_aact.cc +207 −65 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 Loading @@ -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); Loading @@ -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[] = { Loading Loading @@ -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 || Loading @@ -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; Loading Loading @@ -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); { Loading Loading @@ -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 Loading @@ -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 && Loading Loading @@ -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); } } /******************************************************************************* Loading Loading @@ -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__); } }
system/bta/av/bta_av_int.h +27 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 */ Loading Loading @@ -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 Loading Loading @@ -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 ****************************************************************************/ Loading Loading @@ -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 */
system/bta/include/bta_av_api.h +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
system/bta/include/bta_av_co.h +11 −0 Original line number Diff line number Diff line Loading @@ -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 */