Add support for Multi-A2DP state machines per device
* Reimplement most of the BTIF AV state machinery in C++
- Separate the BTIF AV Source from BTIF AV Sink state:
btif_av_source and btif_av_sink
- Remove the single btif_av_cb control block instance
- Add C++ based BtifStateMachine and remove the older C-based
btif_sm state machine
- Introduce C++ class BtifAvPeer to keep state per peer, and use
a single state machine instance per peer
- Update BTA_AvStart() and BTA_AvStop() to take tBTA_AV_HNDL handle
argument
- Register the BTA handles when enabling the Source/Sink service.
This needs to be done in advance during service startup, otherwise
a connection to a remote device will fail.
- Move local event_handler functions inside C++ ProcessEvent methods,
and pocess the BTIF, BTA AV and BTA AVRCP events per state machine
instance
- Cleanup callbacks and use do_in_jni_thread() to schedule the processing
- Add BTIF AV API that needs to be called by the AVRCP module for certain
AVRCP events: btif_av_avrcp_event_open(), btif_av_avrcp_event_close()
btif_av_avrcp_event_remote_play()
- Add a mechanism to set the active device
- Add BluetoothDevice argument to the codec-related internal Binder
APIs: getCodecStatus(), enableOptionalCodecs(),
disableOptionalCodecs(), setCodecConfigPreference()
- Rename btif_av_move_idle() to btif_av_acl_disconnected() and
refactor the processing to happen within each state machine on the
correct thread.
- Process cleanup_src and cleanup_sink on the JNI thread
- Add a mechanism to track the maximum number of connected devices.
- Add unit tests for the new BtifStateMachine class
* Redesign some of the AVDTP internals so it can handle multiple connected
devices
- Change some of the AVDTP struct entries to C++ classes.
This simplifies significantly the design fixes
- Reorganize the AvdtpScb entries: for each connection the
corresponding SEP entries are within the corresponding AvdtpCcb entry.
- Pass peer address as argument to the API functions inside bta_av_co.cc,
and update the peer address inside the corresponding peer entry in
bta_av_co.cc
- Add various log mesages
- Store precomputed BTA AV SCB index in the AvdtpCcb entry and use it as
appropriate.
- Fix the TCID computation and handling for the AvdtpAdaptationLayer
- Fix the computed value for AVDT_NUM_RT_TBL
- Remove video-related code inside AVDTP
- Refactor/cleanup hard-coded callbacks that depend on the BTA_AV_NUM_STRS
value.
- Update various #define values to support a larger number of connected
devices:
- Maximum number of streams:
BTA_AV_NUM_STRS: 2 -> 6
- BT_RC_NUM_APP: 1 -> 12 (AVRCP-related - 2 * MaxDevices)
- MAX_L2CAP_LINKS: 7 -> 13
- MAX_L2CAP_CHANNELS: 16 -> 32
- AVDT_NUM_LINKS: 2 -> 6
- AVDT_NUM_SEPS: (6 * AVDT_NUM_LINKS) -> 6
Now the value is used for the maximum number of SEPs per device
- AVDT_NUM_TC_TBL: 6 -> (AVDT_NUM_SEPS + AVDT_NUM_LINKS)
- AVCT_NUM_LINKS: 2 -> 6
- AVCT_NUM_CONN: 3 -> 14 (2 * MaxDevices + 2)
Also:
- Update the JNI codec-related calls to use const reference
instead of a pointer
- Update the implementation of bta_av_chk_2nd_start() so it is aligned
with bta_av_chk_start() and cleaned up both functions.
- Rename btif_dispatch_sm_event() to btif_av_dispatch_sm_event() and
btif_report_source_codec_state() to btif_av_report_source_codec_state()
for consistency with the rest of the BTIF AV API.
- Add new function btif_rc_is_connected_peer() and remove
btif_rc_get_connected_peer()
- Add new AVRCP header file btif/include/btif_rc.h
and move the AVRCP "extern" declarations from btif_av.cc there.
- Rename btif_av_execute_service() to btif_av_source_execute_service()
- Cleanup the btif_av.h API descriptions
- Print the BTIF AV state in the "dumpsys bluetooth_manager" output
- Print the BTA AV state in the "dumpsys bluetooth_manager" output
- Print the AVDTP state in the "dumpsys bluetooth_manager" output
- Refactor btif_a2dp_source_cb into a class with internal state.
- Refactor A2DP Source worker thread handling and replace it with
libchrome message handler
- Refactor BtaAvCo component (bta_av_co.cc)
- C++ classes and state
- Rename bta_av_co_audio_src_data_path to
bta_av_co_audio_source_data_path
- Remove most BTA_AV_CO_CP_SCMS_T checks
- Replace mutex_global_lock() usage with local mutex
- Keep codec-specific state per peer
- Keep state about the active peer - the first connected peer is the
default active peer
- Report source codec state only for valid peers; i.e., don't report
source codec state for empty RawAddress
- Keep the contect_protect_active flag per peer
- Print the BTA AV CO state in the dumpsys bluetooth_manager" output
- Misc cleanup in BTA AV
- Add ToString() method to struct btav_a2dp_codec_config_t
- Additional cleanup
Bug: 70350399
Test: Manual and unit tests
Change-Id: Icecd7fd44a222d939b63a7473a2239ae0679f08c
Merged-In: Icecd7fd44a222d939b63a7473a2239ae0679f08c
(cherry picked from commit c7242818d4180dec4eae2e75f9fb91f7f6a160aa)
diff --git a/binder/android/bluetooth/IBluetoothA2dp.aidl b/binder/android/bluetooth/IBluetoothA2dp.aidl
index 02a874c..f852d30 100644
--- a/binder/android/bluetooth/IBluetoothA2dp.aidl
+++ b/binder/android/bluetooth/IBluetoothA2dp.aidl
@@ -40,10 +40,11 @@
oneway void adjustAvrcpAbsoluteVolume(int direction);
oneway void setAvrcpAbsoluteVolume(int volume);
boolean isA2dpPlaying(in BluetoothDevice device);
- BluetoothCodecStatus getCodecStatus();
- oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
- oneway void enableOptionalCodecs();
- oneway void disableOptionalCodecs();
+ BluetoothCodecStatus getCodecStatus(in BluetoothDevice device);
+ oneway void setCodecConfigPreference(in BluetoothDevice device,
+ in BluetoothCodecConfig codecConfig);
+ oneway void enableOptionalCodecs(in BluetoothDevice device);
+ oneway void disableOptionalCodecs(in BluetoothDevice device);
int supportsOptionalCodecs(in BluetoothDevice device);
int getOptionalCodecsEnabled(in BluetoothDevice device);
oneway void setOptionalCodecsEnabled(in BluetoothDevice device, int value);
diff --git a/bta/ar/bta_ar.cc b/bta/ar/bta_ar.cc
index b178a07..bcfa89d 100644
--- a/bta/ar/bta_ar.cc
+++ b/bta/ar/bta_ar.cc
@@ -73,13 +73,14 @@
* Returns void
*
******************************************************************************/
-static void bta_ar_avdt_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
+static void bta_ar_avdt_cback(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index) {
/* route the AVDT registration callback to av or avk */
if (bta_ar_cb.p_av_conn_cback)
- (*bta_ar_cb.p_av_conn_cback)(handle, bd_addr, event, p_data);
+ (*bta_ar_cb.p_av_conn_cback)(handle, bd_addr, event, p_data, scb_index);
if (bta_ar_cb.p_avk_conn_cback)
- (*bta_ar_cb.p_avk_conn_cback)(handle, bd_addr, event, p_data);
+ (*bta_ar_cb.p_avk_conn_cback)(handle, bd_addr, event, p_data, scb_index);
}
/*******************************************************************************
@@ -91,7 +92,7 @@
* Returns void
*
******************************************************************************/
-void bta_ar_reg_avdt(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback,
+void bta_ar_reg_avdt(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback,
tBTA_SYS_ID sys_id) {
uint8_t mask = 0;
@@ -153,17 +154,18 @@
* Returns void
*
******************************************************************************/
-void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr) {
+void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr,
+ uint8_t scb_index) {
uint8_t event = BTA_AR_AVDT_CONN_EVT;
tAVDT_CTRL data;
if (sys_id == BTA_ID_AV) {
if (bta_ar_cb.p_avk_conn_cback) {
- (*bta_ar_cb.p_avk_conn_cback)(0, &bd_addr, event, &data);
+ (*bta_ar_cb.p_avk_conn_cback)(0, bd_addr, event, &data, scb_index);
}
} else if (sys_id == BTA_ID_AVK) {
if (bta_ar_cb.p_av_conn_cback) {
- (*bta_ar_cb.p_av_conn_cback)(0, &bd_addr, event, &data);
+ (*bta_ar_cb.p_av_conn_cback)(0, bd_addr, event, &data, scb_index);
}
}
}
diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc
index df7660c..2429bff 100644
--- a/bta/av/bta_av_aact.cc
+++ b/bta/av/bta_av_aact.cc
@@ -24,6 +24,8 @@
*
******************************************************************************/
+#define LOG_TAG "bt_bta_av"
+
#include "bt_target.h"
#include <base/logging.h>
@@ -38,6 +40,7 @@
#include "device/include/interop.h"
#include "l2c_api.h"
#include "l2cdefs.h"
+#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "utl.h"
@@ -84,13 +87,17 @@
};
/* the call out functions for audio stream */
-const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos = {
- bta_av_co_audio_init, bta_av_co_audio_disc_res,
- bta_av_co_audio_getconfig, bta_av_co_audio_setconfig,
- bta_av_co_audio_open, bta_av_co_audio_close,
- bta_av_co_audio_start, bta_av_co_audio_stop,
- bta_av_co_audio_src_data_path, bta_av_co_audio_delay,
- bta_av_co_audio_update_mtu};
+const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos = {bta_av_co_audio_init,
+ bta_av_co_audio_disc_res,
+ bta_av_co_audio_getconfig,
+ bta_av_co_audio_setconfig,
+ bta_av_co_audio_open,
+ bta_av_co_audio_close,
+ bta_av_co_audio_start,
+ bta_av_co_audio_stop,
+ bta_av_co_audio_source_data_path,
+ bta_av_co_audio_delay,
+ bta_av_co_audio_update_mtu};
/* ssm action functions for audio stream */
const tBTA_AV_SACT bta_av_a2dp_action[] = {
@@ -197,47 +204,6 @@
0 /* AVDT_DELAY_REPORT_CFM_EVT */
};
-static void bta_av_stream0_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-static void bta_av_stream1_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#if BTA_AV_NUM_STRS > 2
-static void bta_av_stream2_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-#if BTA_AV_NUM_STRS > 3
-static void bta_av_stream3_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-#if BTA_AV_NUM_STRS > 4
-static void bta_av_stream4_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-#if BTA_AV_NUM_STRS > 5
-static void bta_av_stream5_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
-#endif
-/* the array of callback functions to receive events from AVDT control channel
- */
-tAVDT_CTRL_CBACK* const bta_av_dt_cback[] = {bta_av_stream0_cback,
- bta_av_stream1_cback
-#if BTA_AV_NUM_STRS > 2
- ,
- bta_av_stream2_cback
-#endif
-#if BTA_AV_NUM_STRS > 3
- ,
- bta_av_stream3_cback
-#endif
-#if BTA_AV_NUM_STRS > 4
- ,
- bta_av_stream4_cback
-#endif
-#if BTA_AV_NUM_STRS > 5
- ,
- bta_av_stream5_cback
-#endif
-};
/***********************************************
*
* Function bta_get_scb_handle
@@ -366,7 +332,6 @@
******************************************************************************/
static bool bta_av_next_getcap(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
int i;
- tAVDT_GETCAP_REQ* p_req;
bool sent_cmd = false;
uint16_t uuid_int = p_scb->uuid_int;
uint8_t sep_requested = 0;
@@ -384,14 +349,10 @@
p_scb->sep_info_idx = i;
/* we got a stream; get its capabilities */
- if ((p_scb->avdt_version >= AVDT_VERSION_1_3) &&
- (A2DP_GetAvdtpVersion() >= AVDT_VERSION_1_3)) {
- p_req = AVDT_GetAllCapReq;
- } else {
- p_req = AVDT_GetCapReq;
- }
- (*p_req)(p_scb->peer_addr, p_scb->sep_info[i].seid, &p_scb->peer_cap,
- bta_av_dt_cback[p_scb->hdi]);
+ bool get_all_cap = (p_scb->avdt_version >= AVDT_VERSION_1_3) &&
+ (A2DP_GetAvdtpVersion() >= AVDT_VERSION_1_3);
+ AVDT_GetCapReq(p_scb->peer_addr, p_scb->hdi, p_scb->sep_info[i].seid,
+ &p_scb->peer_cap, &bta_av_proc_stream_evt, get_all_cap);
sent_cmd = true;
break;
}
@@ -416,11 +377,15 @@
* Returns void
*
******************************************************************************/
-static void bta_av_proc_stream_evt(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data,
- int index) {
+void bta_av_proc_stream_evt(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index) {
uint16_t sec_len = 0;
- tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[index];
+ tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[scb_index];
+
+ APPL_TRACE_EVENT(
+ "%s: peer_address: %s avdt_handle: %d event=0x%x scb_index=%d p_scb=%p",
+ __func__, bd_addr.ToString().c_str(), handle, event, scb_index, p_scb);
if (p_data) {
if (event == AVDT_SECURITY_IND_EVT) {
@@ -441,64 +406,17 @@
/* copy event data, bd addr, and handle to event message buffer */
p_msg->hdr.offset = 0;
- if (bd_addr != NULL) {
- p_msg->bd_addr = *bd_addr;
- VLOG(1) << __func__ << ": bd_addr:" << bd_addr;
- }
+ p_msg->bd_addr = bd_addr;
+ p_msg->scb_index = scb_index;
+ APPL_TRACE_EVENT(LOG_TAG, "%s: stream event bd_addr: %s scb_index: %u",
+ __func__, p_msg->bd_addr.ToString().c_str(), scb_index);
if (p_data != NULL) {
memcpy(&p_msg->msg, p_data, sizeof(tAVDT_CTRL));
/* copy config params to event message buffer */
switch (event) {
- case AVDT_RECONFIG_CFM_EVT:
- if (p_msg->msg.hdr.err_code == 0) {
- APPL_TRACE_DEBUG(
- "%s: reconfig cfm event codec info = 0x%06x-%06x-%06x-%02x",
- __func__,
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[0] << 16) +
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[1] << 8) +
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[2],
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[3] << 16) +
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[4] << 8) +
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[5],
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[6] << 16) +
- (p_msg->msg.reconfig_cfm.p_cfg->codec_info[7] << 8) +
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[8],
- p_msg->msg.reconfig_cfm.p_cfg->codec_info[9]);
- }
- break;
-
case AVDT_CONFIG_IND_EVT:
- /* We might have 2 SEP signallings(A2DP + VDP) with one peer device on
- * one L2CAP.
- * If we already have a signalling connection with the bd_addr and the
- * streaming
- * SST is at INIT state, change it to INCOMING state to handle the
- * signalling
- * from the 2nd SEP. */
- if ((bta_av_find_lcb(*bd_addr, BTA_AV_LCB_FIND) != NULL) &&
- (bta_av_is_scb_init(p_scb))) {
- bta_av_set_scb_sst_incoming(p_scb);
-
- /* When ACP_CONNECT_EVT was received, we put first available scb to
- * incoming state.
- * Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and
- * set its state to
- * incoming which we do it above.
- * We also have to set the old p_scb state to init to be used later
- */
- for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
- if ((bta_av_cb.p_scb[i]) && (i != index)) {
- if (bta_av_cb.p_scb[i]->state == BTA_AV_INCOMING_SST) {
- bta_av_cb.p_scb[i]->state = BTA_AV_INIT_SST;
- bta_av_cb.p_scb[i]->coll_mask = 0;
- break;
- }
- }
- }
- }
-
- memcpy(&p_msg->cfg, p_data->config_ind.p_cfg, sizeof(tAVDT_CFG));
+ p_msg->cfg = *p_data->config_ind.p_cfg;
break;
case AVDT_SECURITY_IND_EVT:
@@ -527,8 +445,9 @@
default:
break;
}
- } else
+ } else {
p_msg->msg.hdr.err_code = 0;
+ }
/* look up application event */
if ((p_data == NULL) || (p_data->hdr.err_code == 0)) {
@@ -540,7 +459,7 @@
p_msg->initiator = false;
if (event == AVDT_SUSPEND_CFM_EVT) p_msg->initiator = true;
- APPL_TRACE_VERBOSE("%s: hndl:x%x", __func__, p_scb->hndl);
+ APPL_TRACE_VERBOSE("%s: hndl:0x%x", __func__, p_scb->hndl);
p_msg->hdr.layer_specific = p_scb->hndl;
p_msg->handle = handle;
p_msg->avdt_event = event;
@@ -548,7 +467,7 @@
}
if (p_data) {
- bta_av_conn_cback(handle, bd_addr, event, p_data);
+ bta_av_conn_cback(handle, bd_addr, event, p_data, scb_index);
} else {
APPL_TRACE_ERROR("%s: p_data is null", __func__);
}
@@ -594,104 +513,6 @@
/*******************************************************************************
*
- * Function bta_av_stream0_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream0_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_VERBOSE("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 0);
-}
-
-/*******************************************************************************
- *
- * Function bta_av_stream1_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream1_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 1);
-}
-
-#if BTA_AV_NUM_STRS > 2
-/*******************************************************************************
- *
- * Function bta_av_stream2_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream2_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 2);
-}
-#endif
-
-#if BTA_AV_NUM_STRS > 3
-/*******************************************************************************
- *
- * Function bta_av_stream3_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-static void bta_av_stream3_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 3);
-}
-#endif
-
-/*******************************************************************************
- *
- * Function bta_av_stream4_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-#if BTA_AV_NUM_STRS > 4
-static void bta_av_stream4_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 4);
-}
-#endif
-
-/*******************************************************************************
- *
- * Function bta_av_stream5_cback
- *
- * Description This is the AVDTP callback function for stream events.
- *
- * Returns void
- *
- ******************************************************************************/
-#if BTA_AV_NUM_STRS > 5
-static void bta_av_stream5_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
- APPL_TRACE_EVENT("%s: avdt_handle: %d event=0x%x", __func__, handle, event);
- bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 5);
-}
-#endif
-
-/*******************************************************************************
- *
* Function bta_av_a2dp_sdp_cback
*
* Description A2DP service discovery callback.
@@ -700,18 +521,32 @@
*
******************************************************************************/
static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service) {
- tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
+ APPL_TRACE_DEBUG("%s: found=%s", __func__, (found) ? "true" : "false");
+ tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
if (p_scb == NULL) {
APPL_TRACE_ERROR("%s: no scb found for handle(0x%x)", __func__,
bta_av_cb.handle);
return;
}
+ if (!found) {
+ APPL_TRACE_ERROR("%s: peer %s A2DP service discovery failed", __func__,
+ p_scb->peer_addr.ToString().c_str());
+ }
+ APPL_TRACE_DEBUG("%s: peer %s found=%s", __func__,
+ p_scb->peer_addr.ToString().c_str(),
+ (found) ? "true" : "false");
+
tBTA_AV_SDP_RES* p_msg =
(tBTA_AV_SDP_RES*)osi_malloc(sizeof(tBTA_AV_SDP_RES));
- p_msg->hdr.event =
- (found) ? BTA_AV_SDP_DISC_OK_EVT : BTA_AV_SDP_DISC_FAIL_EVT;
+ if (found) {
+ p_msg->hdr.event = BTA_AV_SDP_DISC_OK_EVT;
+ } else {
+ p_msg->hdr.event = BTA_AV_SDP_DISC_FAIL_EVT;
+ APPL_TRACE_ERROR("%s: BTA_AV_SDP_DISC_FAIL_EVT: peer_addr=%s", __func__,
+ p_scb->peer_addr.ToString().c_str());
+ }
if (found && (p_service != NULL))
p_scb->avdt_version = p_service->avdt_version;
else
@@ -761,7 +596,8 @@
tBTA_AV_RS_RES switch_res = BTA_AV_RS_NONE;
tBTA_AV_API_OPEN* p_buf = &p_scb->q_info.open;
- APPL_TRACE_DEBUG("%s: wait:x%x", __func__, p_scb->wait);
+ APPL_TRACE_DEBUG("%s: peer %s wait:0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->wait);
if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RETRY;
@@ -780,6 +616,8 @@
}
} else {
/* report failure on OPEN */
+ APPL_TRACE_ERROR("%s: peer %s role switch failed (wait=0x%x)", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->wait);
switch_res = BTA_AV_RS_FAIL;
}
@@ -807,7 +645,7 @@
void bta_av_role_res(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
bool initiator = false;
- APPL_TRACE_DEBUG("%s: q_tag:%d, wait:x%x, role:x%x", __func__, p_scb->q_tag,
+ APPL_TRACE_DEBUG("%s: q_tag:%d, wait:0x%x, role:0x%x", __func__, p_scb->q_tag,
p_scb->wait, p_scb->role);
if (p_scb->role & BTA_AV_ROLE_START_INT) initiator = true;
@@ -863,7 +701,7 @@
}
}
- APPL_TRACE_DEBUG("%s: wait:x%x, role:x%x", __func__, p_scb->wait,
+ APPL_TRACE_DEBUG("%s: wait:0x%x, role:0x%x", __func__, p_scb->wait,
p_scb->role);
}
@@ -878,7 +716,11 @@
*
******************************************************************************/
void bta_av_delay_co(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- p_scb->p_cos->delay(p_scb->hndl, p_data->str_msg.msg.delay_rpt_cmd.delay);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d delay:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+ p_data->str_msg.msg.delay_rpt_cmd.delay);
+ p_scb->p_cos->delay(p_scb->hndl, p_scb->peer_addr,
+ p_data->str_msg.msg.delay_rpt_cmd.delay);
}
/*******************************************************************************
@@ -898,7 +740,7 @@
ATTR_ID_BT_PROFILE_DESC_LIST};
uint16_t sdp_uuid = 0; /* UUID for which SDP has to be done */
- APPL_TRACE_DEBUG("%s: use_rc: %d rs:%d, oc:%d", __func__,
+ APPL_TRACE_DEBUG("%s: use_rc: %d switch_res:%d, oc:%d", __func__,
p_data->api_open.use_rc, p_data->api_open.switch_res,
bta_av_cb.audio_open_cnt);
@@ -941,7 +783,7 @@
break;
}
- APPL_TRACE_DEBUG("%s: ok_continue: %d wait:x%x, q_tag: %d", __func__,
+ APPL_TRACE_DEBUG("%s: ok_continue: %d wait:0x%x, q_tag: %d", __func__,
ok_continue, p_scb->wait, p_scb->q_tag);
if (!ok_continue) return;
@@ -1053,7 +895,7 @@
p_scb->offload_start_pending = false;
p_scb->skip_sdp = false;
- if (p_scb->deregistring) {
+ if (p_scb->deregistering) {
/* remove stream */
for (int i = 0; i < BTAV_A2DP_CODEC_INDEX_MAX; i++) {
if (p_scb->seps[i].av_handle) AVDT_RemoveStream(p_scb->seps[i].av_handle);
@@ -1094,7 +936,7 @@
void bta_av_config_ind(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
tBTA_AV_CI_SETCONFIG setconfig;
tAVDT_SEP_INFO* p_info;
- tAVDT_CFG* p_evt_cfg = &p_data->str_msg.cfg;
+ const AvdtpSepConfig* p_evt_cfg = &p_data->str_msg.cfg;
uint8_t psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
uint8_t
local_sep; /* sep type of local handle on which connection was received */
@@ -1103,7 +945,8 @@
local_sep = bta_av_get_scb_sep_type(p_scb, p_msg->handle);
p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
- APPL_TRACE_DEBUG("%s: local_sep = %d", __func__, local_sep);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d local_sep:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl, local_sep);
A2DP_DumpCodecInfo(p_evt_cfg->codec_info);
memcpy(p_scb->cfg.codec_info, p_evt_cfg->codec_info, AVDT_CODEC_SIZE);
@@ -1148,13 +991,13 @@
/* in case of A2DP SINK this is the first time peer data is being sent to
* co functions */
if (local_sep == AVDT_TSEP_SNK) {
- p_scb->p_cos->setcfg(p_scb->hndl, p_evt_cfg->codec_info, p_info->seid,
- p_scb->peer_addr, p_evt_cfg->num_protect,
+ p_scb->p_cos->setcfg(p_scb->hndl, p_scb->peer_addr, p_evt_cfg->codec_info,
+ p_info->seid, p_evt_cfg->num_protect,
p_evt_cfg->protect_info, AVDT_TSEP_SNK,
p_msg->handle);
} else {
- p_scb->p_cos->setcfg(p_scb->hndl, p_evt_cfg->codec_info, p_info->seid,
- p_scb->peer_addr, p_evt_cfg->num_protect,
+ p_scb->p_cos->setcfg(p_scb->hndl, p_scb->peer_addr, p_evt_cfg->codec_info,
+ p_info->seid, p_evt_cfg->num_protect,
p_evt_cfg->protect_info, AVDT_TSEP_SRC,
p_msg->handle);
}
@@ -1183,7 +1026,7 @@
if (bta_av_cb.conn_lcb) {
p_rcb = bta_av_get_rcb_by_shdl((uint8_t)(p_scb->hdi + 1));
if (p_rcb) bta_av_del_rc(p_rcb);
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DisconnectReq(p_scb->peer_addr, &bta_av_proc_stream_evt);
} else {
bta_av_ssm_execute(p_scb, BTA_AV_AVDT_DISCONNECT_EVT, NULL);
}
@@ -1245,7 +1088,8 @@
/* we like this codec_type. find the sep_idx */
local_sep = bta_av_get_scb_sep_type(p_scb, avdt_handle);
bta_av_adjust_seps_idx(p_scb, avdt_handle);
- APPL_TRACE_DEBUG("%s: sep_idx: %d cur_psc_mask:0x%x", __func__,
+ APPL_TRACE_DEBUG("%s: peer %s handle: sep_idx: %d cur_psc_mask:0x%x",
+ __func__, p_scb->peer_addr.ToString().c_str(),
p_scb->sep_idx, p_scb->cur_psc_mask);
if ((AVDT_TSEP_SNK == local_sep) &&
@@ -1267,7 +1111,7 @@
p_scb->wait = BTA_AV_WAIT_ACP_CAPS_ON;
if (p_data->ci_setconfig.recfg_needed)
p_scb->role |= BTA_AV_ROLE_SUSPEND_OPT;
- APPL_TRACE_DEBUG("%s: recfg_needed:%d role:x%x num:%d", __func__,
+ APPL_TRACE_DEBUG("%s: recfg_needed:%d role:0x%x num:%d", __func__,
p_data->ci_setconfig.recfg_needed, p_scb->role, num);
/* callout module tells BTA the number of "good" SEPs and their SEIDs.
* getcap on these SEID */
@@ -1284,7 +1128,7 @@
/* this is called in A2DP SRC path only, In case of SINK we don't need it
*/
if (local_sep == AVDT_TSEP_SRC)
- p_scb->p_cos->disc_res(p_scb->hndl, num, num, 0, p_scb->peer_addr,
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->peer_addr, num, num, 0,
UUID_SERVCLASS_AUDIO_SOURCE);
} else {
/* we do not know the peer device and it is using non-SBC codec
@@ -1326,6 +1170,9 @@
uint8_t* p;
uint16_t mtu;
+ APPL_TRACE_DEBUG("%s: peer %s handle: %d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl);
+
msg.hdr.layer_specific = p_scb->hndl;
msg.is_up = true;
msg.peer_addr = p_scb->peer_addr;
@@ -1350,7 +1197,7 @@
memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
p_scb->l2c_bufs = 0;
- p_scb->p_cos->open(p_scb->hndl, mtu);
+ p_scb->p_cos->open(p_scb->hndl, p_scb->peer_addr, mtu);
{
/* TODO check if other audio channel is open.
@@ -1380,7 +1227,7 @@
}
}
#if (BTA_AR_INCLUDED == TRUE)
- bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr);
+ bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr, p_scb->hdi);
#endif
if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC) {
open.sep = AVDT_TSEP_SNK;
@@ -1504,6 +1351,8 @@
*
******************************************************************************/
void bta_av_connect_req(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
+ APPL_TRACE_DEBUG("%s: peer %s coll_mask:0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->coll_mask);
p_scb->sdp_discovery_started = false;
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
/* SNK initiated L2C connection while SRC was doing SDP. */
@@ -1515,8 +1364,8 @@
return;
}
- AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask,
- bta_av_dt_cback[p_scb->hdi]);
+ AVDT_ConnectReq(p_scb->peer_addr, p_scb->hdi, p_scb->sec_mask,
+ &bta_av_proc_stream_evt);
}
/*******************************************************************************
@@ -1556,7 +1405,9 @@
/* our uuid in case we initiate connection */
uint16_t uuid_int = p_scb->uuid_int;
- APPL_TRACE_DEBUG("%s: initiator UUID 0x%x", __func__, uuid_int);
+ APPL_TRACE_DEBUG("%s: peer %s handle: %d initiator UUID 0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl, uuid_int);
+
/* store number of stream endpoints returned */
p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
@@ -1574,8 +1425,8 @@
}
}
- p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, num_srcs,
- p_scb->peer_addr, uuid_int);
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->peer_addr, p_scb->num_seps,
+ num_snks, num_srcs, uuid_int);
p_scb->num_disc_snks = num_snks;
p_scb->num_disc_srcs = num_srcs;
@@ -1609,6 +1460,9 @@
void bta_av_disc_res_as_acp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
uint8_t num_snks = 0, i;
+ APPL_TRACE_DEBUG("%s: peer %s handle: %d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl);
+
/* store number of stream endpoints returned */
p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
@@ -1620,8 +1474,8 @@
num_snks++;
}
}
- p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, 0,
- p_scb->peer_addr, UUID_SERVCLASS_AUDIO_SOURCE);
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->peer_addr, p_scb->num_seps,
+ num_snks, 0, UUID_SERVCLASS_AUDIO_SOURCE);
p_scb->num_disc_snks = num_snks;
p_scb->num_disc_srcs = 0;
@@ -1651,19 +1505,22 @@
*
******************************************************************************/
void bta_av_save_caps(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tAVDT_CFG cfg;
+ AvdtpSepConfig cfg;
tAVDT_SEP_INFO* p_info = &p_scb->sep_info[p_scb->sep_info_idx];
uint8_t old_wait = p_scb->wait;
bool getcap_done = false;
- APPL_TRACE_DEBUG("%s: num_seps:%d sep_info_idx:%d wait:x%x", __func__,
- p_scb->num_seps, p_scb->sep_info_idx, p_scb->wait);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s handle:%d num_seps:%d sep_info_idx:%d wait:0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->num_seps,
+ p_scb->sep_info_idx, p_scb->wait);
A2DP_DumpCodecInfo(p_scb->peer_cap.codec_info);
- memcpy(&cfg, &p_scb->peer_cap, sizeof(tAVDT_CFG));
+ cfg = p_scb->peer_cap;
/* let application know the capability of the SNK */
- p_scb->p_cos->getcfg(p_scb->hndl, cfg.codec_info, &p_scb->sep_info_idx,
- p_info->seid, &cfg.num_protect, cfg.protect_info);
+ p_scb->p_cos->getcfg(p_scb->hndl, p_scb->peer_addr, cfg.codec_info,
+ &p_scb->sep_info_idx, p_info->seid, &cfg.num_protect,
+ cfg.protect_info);
p_scb->sep_info_idx++;
APPL_TRACE_DEBUG("%s: result: sep_info_idx:%d", __func__,
@@ -1680,7 +1537,7 @@
getcap_done = true;
if (getcap_done) {
- APPL_TRACE_DEBUG("%s: getcap_done: num_seps:%d sep_info_idx:%d wait:x%x",
+ APPL_TRACE_DEBUG("%s: getcap_done: num_seps:%d sep_info_idx:%d wait:0x%x",
__func__, p_scb->num_seps, p_scb->sep_info_idx,
p_scb->wait);
p_scb->wait &= ~(BTA_AV_WAIT_ACP_CAPS_ON | BTA_AV_WAIT_ACP_CAPS_STARTED);
@@ -1715,9 +1572,12 @@
void bta_av_cco_close(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
uint16_t mtu;
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl);
+
mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
- p_scb->p_cos->close(p_scb->hndl);
+ p_scb->p_cos->close(p_scb->hndl, p_scb->peer_addr);
}
/*******************************************************************************
@@ -1778,7 +1638,7 @@
bta_av_data.open = open;
(*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, &bta_av_data);
} else {
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DisconnectReq(p_scb->peer_addr, &bta_av_proc_stream_evt);
}
}
@@ -1794,36 +1654,37 @@
*
******************************************************************************/
void bta_av_getcap_results(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tAVDT_CFG cfg;
- uint8_t media_type;
+ AvdtpSepConfig cfg = p_scb->cfg;
+ uint8_t media_type = A2DP_GetMediaType(p_scb->peer_cap.codec_info);
tAVDT_SEP_INFO* p_info = &p_scb->sep_info[p_scb->sep_info_idx];
- uint16_t uuid_int; /* UUID for which connection was initiatied */
- memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
cfg.num_codec = 1;
cfg.num_protect = p_scb->peer_cap.num_protect;
memcpy(cfg.codec_info, p_scb->peer_cap.codec_info, AVDT_CODEC_SIZE);
memcpy(cfg.protect_info, p_scb->peer_cap.protect_info, AVDT_PROTECT_SIZE);
- media_type = A2DP_GetMediaType(p_scb->peer_cap.codec_info);
- APPL_TRACE_DEBUG("%s: num_codec %d", __func__, p_scb->peer_cap.num_codec);
- APPL_TRACE_DEBUG("%s: media type x%x, x%x", __func__, media_type,
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d num_codec:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+ p_scb->peer_cap.num_codec);
+ APPL_TRACE_DEBUG("%s: media type 0x%x, 0x%x", __func__, media_type,
p_scb->media_type);
A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
/* if codec present and we get a codec configuration */
if ((p_scb->peer_cap.num_codec != 0) && (media_type == p_scb->media_type) &&
- (p_scb->p_cos->getcfg(p_scb->hndl, cfg.codec_info, &p_scb->sep_info_idx,
- p_info->seid, &cfg.num_protect,
- cfg.protect_info) == A2DP_SUCCESS)) {
+ (p_scb->p_cos->getcfg(
+ p_scb->hndl, p_scb->peer_addr, cfg.codec_info, &p_scb->sep_info_idx,
+ p_info->seid, &cfg.num_protect, cfg.protect_info) == A2DP_SUCCESS)) {
+ /* UUID for which connection was initiatied */
+ uint16_t uuid_int = p_scb->uuid_int;
+
/* save copy of codec configuration */
- memcpy(&p_scb->cfg, &cfg, sizeof(tAVDT_CFG));
+ p_scb->cfg = cfg;
APPL_TRACE_DEBUG("%s: result: sep_info_idx=%d", __func__,
p_scb->sep_info_idx);
A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
- uuid_int = p_scb->uuid_int;
APPL_TRACE_DEBUG("%s: initiator UUID = 0x%x", __func__, uuid_int);
if (uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
bta_av_adjust_seps_idx(p_scb,
@@ -1852,7 +1713,7 @@
/* open the stream */
AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
- p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
+ p_scb->hdi, p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
} else {
/* try the next stream, if any */
p_scb->sep_info_idx++;
@@ -1897,8 +1758,8 @@
void bta_av_discover_req(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
/* send avdtp discover request */
- AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS,
- bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DiscoverReq(p_scb->peer_addr, p_scb->hdi, p_scb->sep_info,
+ BTA_AV_NUM_SEPS, &bta_av_proc_stream_evt);
}
/*******************************************************************************
@@ -1931,7 +1792,7 @@
uint8_t policy = HCI_ENABLE_SNIFF_MODE;
uint8_t cur_role;
- APPL_TRACE_DEBUG("%s: sco_occupied:%d, role:x%x, started:%d", __func__,
+ APPL_TRACE_DEBUG("%s: sco_occupied:%d, role:0x%x, started:%d", __func__,
bta_av_cb.sco_occupied, p_scb->role, p_scb->started);
if (bta_av_cb.sco_occupied) {
bta_av_start_failed(p_scb, p_data);
@@ -1963,7 +1824,7 @@
}
}
}
- APPL_TRACE_DEBUG("%s: started %d role:x%x", __func__, p_scb->started,
+ APPL_TRACE_DEBUG("%s: started %d role:0x%x", __func__, p_scb->started,
p_scb->role);
}
@@ -1983,7 +1844,8 @@
BT_HDR* p_buf;
uint8_t policy = HCI_ENABLE_SNIFF_MODE;
- APPL_TRACE_ERROR("%s: audio_open_cnt=%d, p_data %p", __func__,
+ 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);
bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
@@ -2008,7 +1870,7 @@
bta_av_stream_chg(p_scb, false);
p_scb->co_started = false;
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
}
@@ -2075,7 +1937,7 @@
*
******************************************************************************/
void bta_av_reconfig(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tAVDT_CFG* p_cfg;
+ AvdtpSepConfig* p_cfg;
tBTA_AV_API_STOP stop;
tBTA_AV_API_RCFG* p_rcfg = &p_data->api_reconfig;
@@ -2182,7 +2044,7 @@
} else {
new_buf = true;
/* A2DP_list empty, call co_data, dup data to other channels */
- p_buf = (BT_HDR*)p_scb->p_cos->data(p_scb->cfg.codec_info, ×tamp);
+ p_buf = p_scb->p_cos->data(p_scb->cfg.codec_info, ×tamp);
if (p_buf) {
/* use the offset area for the time stamp */
@@ -2202,7 +2064,7 @@
/* opt is a bit mask, it could have several options set */
opt = AVDT_DATA_OPT_NONE;
- if (p_scb->no_rtp_hdr) {
+ if (p_scb->no_rtp_header) {
opt |= AVDT_DATA_OPT_NO_RTP;
}
@@ -2264,7 +2126,7 @@
list_prepend(p_scb->a2dp_list, p_buf);
} else {
/* too many buffers in a2dp_list, drop it. */
- bta_av_co_audio_drop(p_scb->hndl);
+ bta_av_co_audio_drop(p_scb->hndl, p_scb->peer_addr);
osi_free(p_buf);
}
}
@@ -2290,8 +2152,9 @@
uint8_t policy = HCI_ENABLE_SNIFF_MODE;
uint8_t cur_role;
- APPL_TRACE_DEBUG("%s: wait:x%x, role:x%x", __func__, p_scb->wait,
- p_scb->role);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d wait:0x%x, role:0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+ p_scb->wait, p_scb->role);
p_scb->started = true;
p_scb->current_codec = bta_av_get_a2dp_current_codec();
@@ -2311,11 +2174,16 @@
}
if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_FAILED) {
/* role switch has failed */
+ APPL_TRACE_ERROR(
+ "%s: peer %s role switch failed: handle:%d wait:0x%x, role:0x%x",
+ __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->wait,
+ p_scb->role);
p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_FAILED;
p_data = (tBTA_AV_DATA*)&hdr;
hdr.offset = BTA_AV_RS_FAIL;
}
- APPL_TRACE_DEBUG("%s: wait:x%x", __func__, p_scb->wait);
+ APPL_TRACE_DEBUG("%s: peer %s wait:0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->wait);
if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE)) {
p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
@@ -2352,8 +2220,9 @@
}
if (p_scb->wait) {
- APPL_TRACE_ERROR("%s: wait:x%x q_tag:%d- not started", __func__,
- p_scb->wait, p_scb->q_tag);
+ APPL_TRACE_ERROR("%s: peer %s wait:0x%x q_tag:%d not started", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->wait,
+ p_scb->q_tag);
/* Clear first bit of p_scb->wait and not to return from this point else
* HAL layer gets blocked. And if there is delay in Get Capability response
* as
@@ -2379,7 +2248,7 @@
p_scb->co_started = bta_av_cb.audio_open_cnt;
flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1];
} else {
- flush_to = p_bta_av_cfg->video_flush_to;
+ flush_to = 0;
}
L2CA_SetFlushTimeout(p_scb->peer_addr, flush_to);
@@ -2417,12 +2286,14 @@
p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
- p_scb->no_rtp_hdr = false;
- p_scb->p_cos->start(p_scb->hndl, p_scb->cfg.codec_info, &p_scb->no_rtp_hdr);
+ p_scb->no_rtp_header = false;
+ p_scb->p_cos->start(p_scb->hndl, p_scb->peer_addr, p_scb->cfg.codec_info,
+ &p_scb->no_rtp_header);
p_scb->co_started = true;
- APPL_TRACE_DEBUG("%s: suspending: %d, role:x%x, init %d", __func__, suspend,
- p_scb->role, initiator);
+ APPL_TRACE_DEBUG("%s: peer %s suspending: %d, role:0x%x, init %d", __func__,
+ p_scb->peer_addr.ToString().c_str(), suspend, p_scb->role,
+ initiator);
tBTA_AV_START start;
start.suspending = suspend;
@@ -2439,7 +2310,7 @@
p_scb->role |= BTA_AV_ROLE_SUSPEND;
p_scb->cong = true; /* do not allow the media data to go through */
/* do not duplicate the media packets to this channel */
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
p_scb->co_started = false;
stop.flush = false;
stop.suspend = true;
@@ -2485,9 +2356,9 @@
uint8_t policy = HCI_ENABLE_SNIFF_MODE;
APPL_TRACE_WARNING(
- "%s: peer_addr=%s open_status=%d chnl=%d hndl=%d co_started=%d", __func__,
- p_scb->peer_addr.ToString().c_str(), p_scb->open_status, p_scb->chnl,
- p_scb->hndl, p_scb->co_started);
+ "%s: peer %s handle:%d open_status:%d chnl:%d co_started:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->open_status,
+ p_scb->chnl, p_scb->co_started);
if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
bta_av_cb.audio_open_cnt == 1)
@@ -2523,7 +2394,7 @@
}
{
- p_scb->p_cos->close(p_scb->hndl);
+ p_scb->p_cos->close(p_scb->hndl, p_scb->peer_addr);
data.close.chnl = p_scb->chnl;
data.close.hndl = p_scb->hndl;
event = BTA_AV_CLOSE_EVT;
@@ -2545,7 +2416,10 @@
*
******************************************************************************/
void bta_av_clr_cong(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
- if (p_scb->co_started) p_scb->cong = false;
+ APPL_TRACE_DEBUG("%s", __func__);
+ if (p_scb->co_started) {
+ p_scb->cong = false;
+ }
}
/*******************************************************************************
@@ -2562,7 +2436,8 @@
uint8_t err_code = p_data->str_msg.msg.hdr.err_code;
uint8_t policy = HCI_ENABLE_SNIFF_MODE;
- APPL_TRACE_DEBUG("%s: audio_open_cnt = %d, err_code = %d", __func__,
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d audio_open_cnt:%d err_code:%d",
+ __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
bta_av_cb.audio_open_cnt, err_code);
if (!p_scb->started) {
@@ -2621,7 +2496,7 @@
{
p_scb->co_started = false;
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
}
L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
}
@@ -2647,7 +2522,9 @@
******************************************************************************/
void bta_av_rcfg_str_ok(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
- APPL_TRACE_DEBUG("%s: l2c_cid: %d", __func__, p_scb->l2c_cid);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d l2c_cid:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+ p_scb->l2c_cid);
if (p_data != NULL) {
// p_data could be NULL if the reconfig was triggered by the local device
@@ -2657,7 +2534,7 @@
APPL_TRACE_DEBUG("%s: l2c_cid: 0x%x stream_mtu: %d mtu: %d", __func__,
p_scb->l2c_cid, p_scb->stream_mtu, mtu);
if (mtu == 0 || mtu > p_scb->stream_mtu) mtu = p_scb->stream_mtu;
- p_scb->p_cos->update_mtu(p_scb->hndl, mtu);
+ p_scb->p_cos->update_mtu(p_scb->hndl, p_scb->peer_addr, mtu);
}
/* rc listen */
@@ -2710,7 +2587,7 @@
/* open failed. try again */
p_scb->num_recfg++;
if (bta_av_cb.conn_lcb) {
- AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DisconnectReq(p_scb->peer_addr, &bta_av_proc_stream_evt);
} else {
bta_av_connect_req(p_scb, NULL);
}
@@ -2727,15 +2604,18 @@
*
******************************************************************************/
void bta_av_rcfg_connect(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
p_scb->cong = false;
p_scb->num_recfg++;
APPL_TRACE_DEBUG("%s: num_recfg: %d", __func__, p_scb->num_recfg);
if (p_scb->num_recfg > BTA_AV_RECONFIG_RETRY) {
/* let bta_av_rcfg_failed report fail */
bta_av_rcfg_failed(p_scb, NULL);
- } else
- AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask,
- bta_av_dt_cback[p_scb->hdi]);
+ } else {
+ AVDT_ConnectReq(p_scb->peer_addr, p_scb->hdi, p_scb->sec_mask,
+ &bta_av_proc_stream_evt);
+ }
}
/*******************************************************************************
@@ -2764,9 +2644,10 @@
(*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, &bta_av_data);
/* report close event & go to init state */
bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
- } else
- AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask,
- bta_av_dt_cback[p_scb->hdi]);
+ } else {
+ AVDT_ConnectReq(p_scb->peer_addr, p_scb->hdi, p_scb->sec_mask,
+ &bta_av_proc_stream_evt);
+ }
}
/*******************************************************************************
@@ -2782,6 +2663,8 @@
void bta_av_suspend_cont(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
uint8_t err_code = p_data->str_msg.msg.hdr.err_code;
+ APPL_TRACE_DEBUG("%s: err_code=%d", __func__, err_code);
+
p_scb->started = false;
p_scb->cong = false;
if (err_code) {
@@ -2840,9 +2723,10 @@
if (interop_match_name(INTEROP_DISABLE_AVDTP_RECONFIGURE, remote_name) ||
interop_match_addr(INTEROP_DISABLE_AVDTP_RECONFIGURE,
(const RawAddress*)&p_scb->peer_addr)) {
- VLOG(1) << __func__ << ": disable AVDTP RECONFIGURE: interop matched "
- "name "
- << remote_name << " address " << p_scb->peer_addr;
+ LOG_INFO(LOG_TAG,
+ "%s: disable AVDTP RECONFIGURE: interop matched "
+ "name %s address %s",
+ __func__, remote_name, p_scb->peer_addr.ToString().c_str());
disable_avdtp_reconfigure = true;
}
}
@@ -2883,15 +2767,17 @@
*
******************************************************************************/
void bta_av_rcfg_open(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
- APPL_TRACE_DEBUG("%s: num_disc_snks = %d", __func__, p_scb->num_disc_snks);
+ APPL_TRACE_DEBUG("%s: peer %s handle:%d num_disc_snks:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+ p_scb->num_disc_snks);
if (p_scb->num_disc_snks == 0) {
/* Need to update call-out module so that it will be ready for discover */
- p_scb->p_cos->stop(p_scb->hndl);
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
/* send avdtp discover request */
- AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS,
- bta_av_dt_cback[p_scb->hdi]);
+ AVDT_DiscoverReq(p_scb->peer_addr, p_scb->hdi, p_scb->sep_info,
+ BTA_AV_NUM_SEPS, &bta_av_proc_stream_evt);
} else {
APPL_TRACE_DEBUG("%s: calling AVDT_OpenReq()", __func__);
A2DP_DumpCodecInfo(p_scb->cfg.codec_info);
@@ -2902,7 +2788,7 @@
/* open the stream with the new config */
p_scb->sep_info_idx = p_scb->rcfg_idx;
- AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr,
+ AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr, p_scb->hdi,
p_scb->sep_info[p_scb->sep_info_idx].seid, &p_scb->cfg);
}
}
@@ -2934,25 +2820,23 @@
******************************************************************************/
void bta_av_chk_2nd_start(tBTA_AV_SCB* p_scb,
UNUSED_ATTR tBTA_AV_DATA* p_data) {
- tBTA_AV_SCB* p_scbi;
- int i;
- bool new_started = false;
-
- if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2)) {
- /* more than one audio channel is connected */
+ if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2) &&
+ (((p_scb->role & BTA_AV_ROLE_AD_ACP) == 0) || // Outgoing connection or
+ (bta_av_cb.features & BTA_AV_FEAT_ACP_START))) { // Auto-starting option
+ // More than one audio channel is connected.
if (!(p_scb->role & BTA_AV_ROLE_SUSPEND_OPT)) {
- /* this channel does not need to be reconfigured.
- * if there is other channel streaming, start the stream now */
- for (i = 0; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
+ // This channel does not need to be reconfigured.
+ // If there is other channel streaming, start the stream now.
+ bool new_started = false;
+ for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
+ tBTA_AV_SCB* p_scbi = bta_av_cb.p_scb[i];
if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started) {
if (!new_started) {
- /* start the new stream */
+ // Start the new stream
new_started = true;
bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
}
- /* may need to update the flush timeout of this already started stream
- */
+ // May need to update the flush timeout of this already started stream
if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
p_scbi->co_started = bta_av_cb.audio_open_cnt;
L2CA_SetFlushTimeout(
@@ -2975,7 +2859,7 @@
*
******************************************************************************/
void bta_av_open_rc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- APPL_TRACE_DEBUG("%s: use_rc: %d, wait: x%x role:x%x", __func__,
+ APPL_TRACE_DEBUG("%s: use_rc: %d, wait: 0x%x role: 0x%x", __func__,
p_scb->use_rc, p_scb->wait, p_scb->role);
if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) &&
(p_scb->q_tag == BTA_AV_Q_TAG_START)) {
@@ -3043,6 +2927,9 @@
void bta_av_open_at_inc(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
memcpy(&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
+ APPL_TRACE_DEBUG("%s: peer %s coll_mask:0x%x", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->coll_mask);
+
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index 5dcb95b..099731e 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -109,7 +109,7 @@
p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
}
if (p_scb) {
- APPL_TRACE_DEBUG("bta_av_del_rc shdl:%d, srch:%d rc_handle:%d",
+ APPL_TRACE_DEBUG("%s: shdl:%d, srch:%d rc_handle:%d", __func__,
p_rcb->shdl, p_scb->rc_handle, p_rcb->handle);
if (p_scb->rc_handle == p_rcb->handle)
p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
@@ -120,10 +120,9 @@
}
}
- APPL_TRACE_EVENT(
- "bta_av_del_rc handle: %d status=0x%x, rc_acp_handle:%d, idx:%d",
- p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle,
- bta_av_cb.rc_acp_idx);
+ APPL_TRACE_EVENT("%s: handle: %d status=0x%x, rc_acp_handle:%d, idx:%d",
+ __func__, p_rcb->handle, p_rcb->status,
+ bta_av_cb.rc_acp_handle, bta_av_cb.rc_acp_idx);
rc_handle = p_rcb->handle;
if (!(p_rcb->status & BTA_AV_RC_CONN_MASK) ||
((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) {
@@ -137,8 +136,9 @@
if (rc_handle == bta_av_cb.rc_acp_handle)
bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
APPL_TRACE_EVENT(
- "end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d",
- p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, p_rcb->lidx);
+ "%s: end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d",
+ __func__, p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle,
+ p_rcb->lidx);
}
}
@@ -207,7 +207,7 @@
const RawAddress* peer_addr) {
uint16_t msg_event = 0;
- APPL_TRACE_EVENT("%s handle: %d event=0x%x", __func__, handle, event);
+ APPL_TRACE_EVENT("%s: handle: %d event=0x%x", __func__, handle, event);
if (event == AVRC_OPEN_IND_EVT) {
/* save handle of opened connection
bta_av_cb.rc_handle = handle;*/
@@ -245,7 +245,7 @@
uint8_t* p_data_src = NULL;
uint16_t data_len = 0;
- APPL_TRACE_DEBUG("%s handle: %u opcode=0x%x", __func__, handle, opcode);
+ APPL_TRACE_DEBUG("%s: handle: %u opcode=0x%x", __func__, handle, opcode);
/* Copy avrc packet into BTA message buffer (for sending to BTA state machine)
*/
@@ -317,7 +317,7 @@
} else {
p_rcb = bta_av_get_rcb_by_shdl(shdl);
if (p_rcb != NULL) {
- APPL_TRACE_ERROR("bta_av_rc_create ACP handle exist for shdl:%d", shdl);
+ APPL_TRACE_ERROR("%s: ACP handle exist for shdl:%d", __func__, shdl);
return p_rcb->handle;
}
}
@@ -338,7 +338,7 @@
p_rcb = &p_cb->rcb[i];
if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {
- APPL_TRACE_ERROR("bta_av_rc_create found duplicated handle:%d", rc_handle);
+ APPL_TRACE_ERROR("%s: found duplicated handle:%d", __func__, rc_handle);
}
p_rcb->handle = rc_handle;
@@ -350,12 +350,12 @@
/* this LIDX is reserved for the AVRCP ACP connection */
p_cb->rc_acp_handle = p_rcb->handle;
p_cb->rc_acp_idx = (i + 1);
- APPL_TRACE_DEBUG("rc_acp_handle:%d idx:%d", p_cb->rc_acp_handle,
- p_cb->rc_acp_idx);
+ APPL_TRACE_DEBUG("%s: rc_acp_handle:%d idx:%d", __func__,
+ p_cb->rc_acp_handle, p_cb->rc_acp_idx);
}
APPL_TRACE_DEBUG(
- "create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x", i,
- role, shdl, p_rcb->handle, lidx, p_rcb->status);
+ "%s: create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x",
+ __func__, i, role, shdl, p_rcb->handle, lidx, p_rcb->status);
return rc_handle;
}
@@ -441,13 +441,15 @@
uint8_t mask;
tBTA_AV_LCB* p_lcb = NULL;
+ APPL_TRACE_DEBUG("%s: address: %s op:%d", __func__, addr.ToString().c_str(),
+ op);
for (xx = 0; xx < BTA_AV_NUM_LINKS; xx++) {
mask = 1 << xx; /* the used mask for this lcb */
if ((mask & p_cb->conn_lcb) && p_cb->lcb[xx].addr == addr) {
p_lcb = &p_cb->lcb[xx];
if (op == BTA_AV_LCB_FREE) {
p_cb->conn_lcb &= ~mask; /* clear the connect mask */
- APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
+ APPL_TRACE_DEBUG("%s: conn_lcb: 0x%x", __func__, p_cb->conn_lcb);
}
break;
}
@@ -479,10 +481,10 @@
p_scb = p_cb->p_scb[i];
if (p_scb && p_scb->peer_addr == p_data->rc_conn_chg.peer_addr) {
p_scb->rc_handle = p_data->rc_conn_chg.handle;
- APPL_TRACE_DEBUG("bta_av_rc_opened shdl:%d, srch %d", i + 1,
+ APPL_TRACE_DEBUG("%s: shdl:%d, srch %d", __func__, i + 1,
p_scb->rc_handle);
shdl = i + 1;
- LOG_INFO(LOG_TAG, "%s allow incoming AVRCP connections:%d", __func__,
+ LOG_INFO(LOG_TAG, "%s: allow incoming AVRCP connections:%d", __func__,
p_scb->use_rc);
alarm_cancel(p_scb->avrc_ct_timer);
disc = p_scb->hndl;
@@ -492,11 +494,11 @@
i = p_data->rc_conn_chg.handle;
if (p_cb->rcb[i].handle == BTA_AV_RC_HANDLE_NONE) {
- APPL_TRACE_ERROR("not a valid handle:%d any more", i);
+ APPL_TRACE_ERROR("%s: not a valid handle:%d any more", __func__, i);
return;
}
- APPL_TRACE_DEBUG("%s local features %d peer features %d", __func__,
+ APPL_TRACE_DEBUG("%s: local features %d peer features %d", __func__,
p_cb->features, p_cb->rcb[i].peer_features);
/* listen to browsing channel when the connection is open,
@@ -515,14 +517,14 @@
p_cb->rcb[i].lidx = tmp;
p_cb->rc_acp_handle = p_rcb->handle;
p_cb->rc_acp_idx = (p_rcb - p_cb->rcb) + 1;
- APPL_TRACE_DEBUG("switching RCB rc_acp_handle:%d idx:%d",
+ APPL_TRACE_DEBUG("%s: switching RCB rc_acp_handle:%d idx:%d", __func__,
p_cb->rc_acp_handle, p_cb->rc_acp_idx);
}
}
p_cb->rcb[i].shdl = shdl;
rc_open.rc_handle = i;
- APPL_TRACE_ERROR("bta_av_rc_opened rcb[%d] shdl:%d lidx:%d/%d", i, shdl,
+ APPL_TRACE_ERROR("%s: rcb[%d] shdl:%d lidx:%d/%d", __func__, i, shdl,
p_cb->rcb[i].lidx, p_cb->lcb[BTA_AV_NUM_LINKS].lidx);
p_cb->rcb[i].status |= BTA_AV_RC_CONN_MASK;
@@ -531,19 +533,19 @@
* update the index to the extra LCB */
p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
p_lcb->addr = p_data->rc_conn_chg.peer_addr;
- VLOG(1) << "rc_only bd_addr:" << p_lcb->addr;
p_lcb->lidx = BTA_AV_NUM_LINKS + 1;
p_cb->rcb[i].lidx = p_lcb->lidx;
p_lcb->conn_msk = 1;
- APPL_TRACE_ERROR("rcb[%d].lidx=%d, lcb.conn_msk=x%x", i, p_cb->rcb[i].lidx,
- p_lcb->conn_msk);
+ APPL_TRACE_ERROR("%s: bd_addr: %s rcb[%d].lidx=%d, lcb.conn_msk=x%x",
+ __func__, p_lcb->addr.ToString().c_str(), i,
+ p_cb->rcb[i].lidx, p_lcb->conn_msk);
disc = p_data->rc_conn_chg.handle | BTA_AV_CHNL_MSK;
}
rc_open.peer_addr = p_data->rc_conn_chg.peer_addr;
rc_open.peer_features = p_cb->rcb[i].peer_features;
rc_open.status = BTA_AV_SUCCESS;
- APPL_TRACE_DEBUG("%s local features:x%x peer_features:x%x", __func__,
+ APPL_TRACE_DEBUG("%s: local features:x%x peer_features:x%x", __func__,
p_cb->features, rc_open.peer_features);
if (rc_open.peer_features == 0) {
/* we have not done SDP on peer RC capabilities.
@@ -566,7 +568,7 @@
if ((p_cb->features & BTA_AV_FEAT_BROWSE) &&
(rc_open.peer_features & BTA_AV_FEAT_BROWSE) &&
((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) {
- APPL_TRACE_DEBUG("%s opening AVRC Browse channel", __func__);
+ APPL_TRACE_DEBUG("%s: opening AVRC Browse channel", __func__);
AVRC_OpenBrowse(p_data->rc_conn_chg.handle, AVCT_INT);
}
}
@@ -751,21 +753,22 @@
if ((AVRC_MIN_META_CMD_LEN + p_vendor->vendor_len) > AVRC_META_CMD_BUF_SIZE) {
/* reject it */
p_rc_rsp->rsp.status = AVRC_STS_BAD_PARAM;
- APPL_TRACE_ERROR("%s Invalid meta-command length: %d", __func__,
+ APPL_TRACE_ERROR("%s: Invalid meta-command length: %d", __func__,
p_vendor->vendor_len);
return 0;
}
/* Metadata messages only use PANEL sub-unit type */
if (p_vendor->hdr.subunit_type != AVRC_SUB_PANEL) {
- APPL_TRACE_DEBUG("SUBUNIT must be PANEL");
+ APPL_TRACE_DEBUG("%s: SUBUNIT must be PANEL", __func__);
/* reject it */
evt = 0;
p_vendor->hdr.ctype = AVRC_RSP_NOT_IMPL;
p_vendor->vendor_len = 0;
p_rc_rsp->rsp.status = AVRC_STS_BAD_PARAM;
} else if (!AVRC_IsValidAvcType(pdu, p_vendor->hdr.ctype)) {
- APPL_TRACE_DEBUG("Invalid pdu/ctype: 0x%x, %d", pdu, p_vendor->hdr.ctype);
+ APPL_TRACE_DEBUG("%s: Invalid pdu/ctype: 0x%x, %d", __func__, pdu,
+ p_vendor->hdr.ctype);
/* reject invalid message without reporting to app */
evt = 0;
p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD;
@@ -794,7 +797,7 @@
memcpy(p_rc_rsp->get_caps.param.event_id,
p_bta_av_cfg->p_meta_evt_ids, p_bta_av_cfg->num_evt_ids);
} else {
- APPL_TRACE_DEBUG("Invalid capability ID: 0x%x", u8);
+ APPL_TRACE_DEBUG("%s: Invalid capability ID: 0x%x", __func__, u8);
/* reject - unknown capability ID */
p_rc_rsp->get_caps.status = AVRC_STS_BAD_PARAM;
}
@@ -834,7 +837,7 @@
rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
if (NULL == p_data) {
- APPL_TRACE_ERROR("Message from peer with no data in %s", __func__);
+ APPL_TRACE_ERROR("%s: Message from peer with no data", __func__);
return;
}
@@ -865,7 +868,7 @@
bta_av_op_supported(p_data->rc_msg.msg.pass.op_id, is_inquiry);
}
- APPL_TRACE_DEBUG("ctype %d", p_data->rc_msg.msg.hdr.ctype)
+ APPL_TRACE_DEBUG("%s: ctype %d", __func__, p_data->rc_msg.msg.hdr.ctype)
/* send response */
if (p_data->rc_msg.msg.hdr.ctype != AVRC_RSP_INTERIM)
@@ -899,7 +902,7 @@
(p_data->rc_msg.msg.pass.pass_len > 0)) {
av.remote_rsp.p_data =
(uint8_t*)osi_malloc(p_data->rc_msg.msg.pass.pass_len);
- APPL_TRACE_DEBUG("Vendor Unique data len = %d",
+ APPL_TRACE_DEBUG("%s: Vendor Unique data len = %d", __func__,
p_data->rc_msg.msg.pass.pass_len);
memcpy(av.remote_rsp.p_data, p_data->rc_msg.msg.pass.p_pass_data,
p_data->rc_msg.msg.pass.pass_len);
@@ -1002,7 +1005,7 @@
if (handle < BTA_AV_NUM_RCB) {
p_rcb = &p_cb->rcb[handle];
- APPL_TRACE_DEBUG("%s handle: %d, status=0x%x", __func__, p_rcb->handle,
+ APPL_TRACE_DEBUG("%s: handle: %d, status=0x%x", __func__, p_rcb->handle,
p_rcb->status);
if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {
if (p_rcb->shdl) {
@@ -1030,7 +1033,7 @@
*
******************************************************************************/
void bta_av_rc_browse_close(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {
- APPL_TRACE_WARNING("%s empty placeholder does nothing!", __func__);
+ APPL_TRACE_WARNING("%s: empty placeholder does nothing!", __func__);
}
/*******************************************************************************
@@ -1063,54 +1066,19 @@
*
******************************************************************************/
void bta_av_stream_chg(tBTA_AV_SCB* p_scb, bool started) {
- uint8_t started_msk;
- int i;
- uint8_t* p_streams;
- bool no_streams = false;
- tBTA_AV_SCB* p_scbi;
+ uint8_t started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- APPL_TRACE_DEBUG("bta_av_stream_chg started:%d started_msk:x%x chnl:x%x",
- started, started_msk, p_scb->chnl);
- if (BTA_AV_CHNL_AUDIO == p_scb->chnl)
- p_streams = &bta_av_cb.audio_streams;
- else
- p_streams = &bta_av_cb.video_streams;
+ APPL_TRACE_DEBUG("%s: started:%d started_msk:x%x", __func__, started,
+ started_msk);
if (started) {
+ bta_av_cb.audio_streams |= started_msk;
/* Let L2CAP know this channel is processed with high priority */
L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_HIGH);
- (*p_streams) |= started_msk;
} else {
- (*p_streams) &= ~started_msk;
- }
-
- if (!started) {
- i = 0;
- if (BTA_AV_CHNL_AUDIO == p_scb->chnl) {
- if (bta_av_cb.video_streams == 0) no_streams = true;
- } else {
- no_streams = true;
- if (bta_av_cb.audio_streams) {
- for (; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
- /* scb is used and started */
- if (p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i)) &&
- p_scbi->peer_addr == p_scb->peer_addr) {
- no_streams = false;
- break;
- }
- }
- }
- }
-
- APPL_TRACE_DEBUG("no_streams:%d i:%d, audio_streams:x%x, video_streams:x%x",
- no_streams, i, bta_av_cb.audio_streams,
- bta_av_cb.video_streams);
- if (no_streams) {
- /* Let L2CAP know this channel is processed with low priority */
- L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_NORMAL);
- }
+ bta_av_cb.audio_streams &= ~started_msk;
+ /* Let L2CAP know this channel is processed with low priority */
+ L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_NORMAL);
}
}
@@ -1154,39 +1122,35 @@
if (bta_av_cb.rcb[i].lidx == p_lcb->lidx) {
bta_av_cb.rcb[i].shdl = index + 1;
APPL_TRACE_DEBUG(
- "conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
- bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
+ "%s: conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d",
+ __func__, i, bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
break;
}
}
}
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- old_msk = p_cb->conn_audio;
- p_cb->conn_audio |= mask;
- } else {
- old_msk = p_cb->conn_video;
- p_cb->conn_video |= mask;
- }
+ old_msk = p_cb->conn_audio;
+ p_cb->conn_audio |= mask;
if ((old_msk & mask) == 0) {
/* increase the audio open count, if not set yet */
bta_av_cb.audio_open_cnt++;
}
- APPL_TRACE_DEBUG("rc_acp_handle:%d rc_acp_idx:%d", p_cb->rc_acp_handle,
- p_cb->rc_acp_idx);
+ APPL_TRACE_DEBUG("%s: rc_acp_handle:%d rc_acp_idx:%d", __func__,
+ p_cb->rc_acp_handle, p_cb->rc_acp_idx);
/* check if the AVRCP ACP channel is already connected */
if (p_lcb && p_cb->rc_acp_handle != BTA_AV_RC_HANDLE_NONE &&
p_cb->rc_acp_idx) {
p_lcb_rc = &p_cb->lcb[BTA_AV_NUM_LINKS];
APPL_TRACE_DEBUG(
- "rc_acp is connected && conn_chg on same addr "
+ "%s: rc_acp is connected && conn_chg on same addr "
"p_lcb_rc->conn_msk:x%x",
- p_lcb_rc->conn_msk);
+ __func__, p_lcb_rc->conn_msk);
/* check if the RC is connected to the scb addr */
- VLOG(1) << "p_lcb_rc->addr: " << p_lcb_rc->addr
- << " conn_chg.peer_addr:" << p_data->conn_chg.peer_addr;
+ LOG_INFO(LOG_TAG, "%s: p_lcb_rc->addr: %s conn_chg.peer_addr: %s",
+ __func__, p_lcb_rc->addr.ToString().c_str(),
+ p_data->conn_chg.peer_addr.ToString().c_str());
if (p_lcb_rc->conn_msk &&
p_lcb_rc->addr == p_data->conn_chg.peer_addr) {
@@ -1197,23 +1161,25 @@
p_scb->rc_handle = p_cb->rc_acp_handle;
p_rcb = &p_cb->rcb[p_cb->rc_acp_idx - 1];
p_rcb->shdl = bta_av_get_shdl(p_scb);
- APPL_TRACE_DEBUG("update rc_acp shdl:%d/%d srch:%d", index + 1,
- p_rcb->shdl, p_scb->rc_handle);
+ APPL_TRACE_DEBUG("%s: update rc_acp shdl:%d/%d srch:%d", index + 1,
+ __func__, p_rcb->shdl, p_scb->rc_handle);
p_rcb2 = bta_av_get_rcb_by_shdl(p_rcb->shdl);
if (p_rcb2) {
/* found the RCB that was created to associated with this SCB */
p_cb->rc_acp_handle = p_rcb2->handle;
p_cb->rc_acp_idx = (p_rcb2 - p_cb->rcb) + 1;
- APPL_TRACE_DEBUG("new rc_acp_handle:%d, idx:%d",
+ APPL_TRACE_DEBUG("%s: new rc_acp_handle:%d, idx:%d", __func__,
p_cb->rc_acp_handle, p_cb->rc_acp_idx);
p_rcb2->lidx = (BTA_AV_NUM_LINKS + 1);
- APPL_TRACE_DEBUG("rc2 handle:%d lidx:%d/%d", p_rcb2->handle,
- p_rcb2->lidx, p_cb->lcb[p_rcb2->lidx - 1].lidx);
+ APPL_TRACE_DEBUG("%s: rc2 handle:%d lidx:%d/%d", __func__,
+ p_rcb2->handle, p_rcb2->lidx,
+ p_cb->lcb[p_rcb2->lidx - 1].lidx);
}
p_rcb->lidx = p_lcb->lidx;
- APPL_TRACE_DEBUG("rc handle:%d lidx:%d/%d", p_rcb->handle,
- p_rcb->lidx, p_cb->lcb[p_rcb->lidx - 1].lidx);
+ APPL_TRACE_DEBUG("%s: rc handle:%d lidx:%d/%d", __func__,
+ p_rcb->handle, p_rcb->lidx,
+ p_cb->lcb[p_rcb->lidx - 1].lidx);
}
}
}
@@ -1225,7 +1191,6 @@
/* clear the conned mask for this channel */
p_cb->conn_audio &= ~mask;
- p_cb->conn_video &= ~mask;
if (p_scb) {
/* the stream is closed.
* clear the peer address, so it would not mess up the AVRCP for the next
@@ -1245,11 +1210,12 @@
}
}
- APPL_TRACE_DEBUG("bta_av_conn_chg shdl:%d", index + 1);
+ APPL_TRACE_DEBUG("%s: shdl:%d", __func__, index + 1);
for (i = 0; i < BTA_AV_NUM_RCB; i++) {
- APPL_TRACE_DEBUG("conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
- bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
- bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
+ APPL_TRACE_DEBUG("%s: conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d",
+ __func__, i, bta_av_cb.rcb[i].handle,
+ bta_av_cb.rcb[i].status, bta_av_cb.rcb[i].shdl,
+ bta_av_cb.rcb[i].lidx);
if (bta_av_cb.rcb[i].shdl == index + 1) {
bta_av_del_rc(&bta_av_cb.rcb[i]);
/* since the connection is already down and info was removed, clean
@@ -1259,7 +1225,7 @@
}
}
- if (p_cb->conn_audio == 0 && p_cb->conn_video == 0) {
+ if (p_cb->conn_audio == 0) {
/* if both channels are not connected,
* close all RC channels */
bta_av_close_all_rc(p_cb);
@@ -1272,10 +1238,10 @@
}
APPL_TRACE_DEBUG(
- "bta_av_conn_chg audio:%x video:%x up:%d conn_msk:0x%x chk_restore:%d "
+ "%s: audio:%x up:%d conn_msk:0x%x chk_restore:%d "
"audio_open_cnt:%d",
- p_cb->conn_audio, p_cb->conn_video, p_data->conn_chg.is_up, conn_msk,
- chk_restore, p_cb->audio_open_cnt);
+ __func__, p_cb->conn_audio, p_data->conn_chg.is_up, conn_msk, chk_restore,
+ p_cb->audio_open_cnt);
if (chk_restore) {
if (p_cb->audio_open_cnt == 1) {
@@ -1368,14 +1334,14 @@
uint8_t mask;
tBTA_AV_LCB* p_lcb = NULL;
- APPL_TRACE_DEBUG("bta_av_sig_chg event: %d", event);
+ APPL_TRACE_DEBUG("%s: event: %d", __func__, event);
if (event == AVDT_CONNECT_IND_EVT) {
p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FIND);
if (!p_lcb) {
/* if the address does not have an LCB yet, alloc one */
for (xx = 0; xx < BTA_AV_NUM_LINKS; xx++) {
mask = 1 << xx;
- APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
+ APPL_TRACE_DEBUG("%s: conn_lcb: 0x%x", __func__, p_cb->conn_lcb);
/* look for a p_lcb with its p_scb registered */
if ((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL)) {
p_lcb = &p_cb->lcb[xx];
@@ -1388,10 +1354,11 @@
}
/* this entry is not used yet. */
p_cb->conn_lcb |= mask; /* mark it as used */
- APPL_TRACE_DEBUG("start sig timer %d", p_data->hdr.offset);
+ APPL_TRACE_DEBUG("%s: start sig timer %d", __func__,
+ p_data->hdr.offset);
if (p_data->hdr.offset == AVDT_ACP) {
- APPL_TRACE_DEBUG("Incoming L2CAP acquired, set state as incoming",
- NULL);
+ APPL_TRACE_DEBUG(
+ "%s: Incoming L2CAP acquired, set state as incoming", __func__);
p_cb->p_scb[xx]->peer_addr = p_data->str_msg.bd_addr;
p_cb->p_scb[xx]->use_rc =
true; /* allowing RC for incoming connection */
@@ -1425,7 +1392,8 @@
if (xx == BTA_AV_NUM_LINKS) {
/* We do not have scb for this avdt connection. */
/* Silently close the connection. */
- APPL_TRACE_ERROR("av scb not available for avdt connection");
+ APPL_TRACE_ERROR("%s: av scb not available for avdt connection",
+ __func__);
AVDT_DisconnectReq(p_data->str_msg.bd_addr, NULL);
return;
}
@@ -1443,7 +1411,7 @@
p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FREE);
if (p_lcb && (p_lcb->conn_msk || bta_av_cb.conn_lcb)) {
- APPL_TRACE_DEBUG("conn_msk: 0x%x", p_lcb->conn_msk);
+ APPL_TRACE_DEBUG("%s: conn_msk: 0x%x", __func__, p_lcb->conn_msk);
/* clean up ssm */
for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
if (p_cb->p_scb[xx] &&
@@ -1523,7 +1491,7 @@
p_scb = p_cb->p_scb[inx];
}
if (p_scb) {
- APPL_TRACE_DEBUG("%s coll_mask = 0x%02X", __func__, p_scb->coll_mask);
+ APPL_TRACE_DEBUG("%s: coll_mask = 0x%02X", __func__, p_scb->coll_mask);
if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
p_scb->coll_mask &= ~BTA_AV_COLL_INC_TMR;
@@ -1580,7 +1548,7 @@
uint16_t peer_rc_version = 0;
uint16_t categories = 0;
- APPL_TRACE_DEBUG("bta_av_check_peer_features service_uuid:x%x", service_uuid);
+ APPL_TRACE_DEBUG("%s: service_uuid:x%x", __func__, service_uuid);
/* loop through all records we found */
while (true) {
/* get next record; if none found, we're done */
@@ -1606,7 +1574,7 @@
/* get profile version (if failure, version parameter is not updated) */
SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL,
&peer_rc_version);
- APPL_TRACE_DEBUG("peer_rc_version 0x%x", peer_rc_version);
+ APPL_TRACE_DEBUG("%s: peer_rc_version 0x%x", __func__, peer_rc_version);
if (peer_rc_version >= AVRC_REV_1_3)
peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
@@ -1624,7 +1592,7 @@
}
}
}
- APPL_TRACE_DEBUG("peer_features:x%x", peer_features);
+ APPL_TRACE_DEBUG("%s: peer_features:x%x", __func__, peer_features);
return peer_features;
}
@@ -1642,13 +1610,14 @@
tBTA_AV_FEAT peer_features = 0;
tBTA_AV_CB* p_cb = &bta_av_cb;
- APPL_TRACE_DEBUG("%s service_uuid:x%x", __func__, service_uuid);
+ APPL_TRACE_DEBUG("%s: service_uuid:x%x", __func__, service_uuid);
/* loop through all records we found */
tSDP_DISC_REC* p_rec =
SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, NULL);
while (p_rec) {
- APPL_TRACE_DEBUG("%s found Service record for x%x", __func__, service_uuid);
+ APPL_TRACE_DEBUG("%s: found Service record for x%x", __func__,
+ service_uuid);
if ((SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_CLASS_ID_LIST)) !=
NULL) {
@@ -1668,7 +1637,7 @@
uint16_t peer_rc_version = 0;
bool val = SDP_FindProfileVersionInRec(
p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_rc_version);
- APPL_TRACE_DEBUG("%s peer_rc_version for TG 0x%x, profile_found %d",
+ APPL_TRACE_DEBUG("%s: peer_rc_version for TG 0x%x, profile_found %d",
__func__, peer_rc_version, val);
if (peer_rc_version >= AVRC_REV_1_3)
@@ -1699,7 +1668,7 @@
/* get next record; if none found, we're done */
p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, p_rec);
}
- APPL_TRACE_DEBUG("%s peer_features:x%x", __func__, peer_features);
+ APPL_TRACE_DEBUG("%s: peer_features:x%x", __func__, peer_features);
return peer_features;
}
@@ -1720,7 +1689,7 @@
uint8_t rc_handle;
tBTA_AV_FEAT peer_features = 0; /* peer features mask */
- APPL_TRACE_DEBUG("%s bta_av_rc_disc_done disc:x%x", __func__, p_cb->disc);
+ APPL_TRACE_DEBUG("%s: bta_av_rc_disc_done disc:x%x", __func__, p_cb->disc);
if (!p_cb->disc) {
return;
}
@@ -1741,13 +1710,13 @@
}
}
- APPL_TRACE_DEBUG("%s rc_handle %d", __func__, rc_handle);
+ APPL_TRACE_DEBUG("%s: rc_handle %d", __func__, rc_handle);
#if (BTA_AV_SINK_INCLUDED == TRUE)
if (p_cb->sdp_a2dp_snk_handle) {
/* This is Sink + CT + TG(Abs Vol) */
peer_features =
bta_avk_check_peer_features(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
- APPL_TRACE_DEBUG("%s populating rem ctrl target features %d", __func__,
+ APPL_TRACE_DEBUG("%s: populating rem ctrl target features %d", __func__,
peer_features);
if (BTA_AV_FEAT_ADV_CTRL &
bta_avk_check_peer_features(UUID_SERVCLASS_AV_REMOTE_CONTROL))
@@ -1778,7 +1747,7 @@
SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL,
&peer_rc_version);
if (peer_rc_version <= AVRC_REV_1_3) {
- APPL_TRACE_DEBUG("%s Using AVRCP 1.3 Capabilities with remote device",
+ APPL_TRACE_DEBUG("%s: Using AVRCP 1.3 Capabilities with remote device",
__func__);
p_bta_av_cfg = &bta_av_cfg_compatibility;
}
@@ -1788,8 +1757,8 @@
p_cb->disc = 0;
osi_free_and_reset((void**)&p_cb->p_disc_db);
- APPL_TRACE_DEBUG("peer_features 0x%x, features 0x%x", peer_features,
- p_cb->features);
+ APPL_TRACE_DEBUG("%s: peer_features 0x%x, features 0x%x", __func__,
+ peer_features, p_cb->features);
/* if we have no rc connection */
if (rc_handle == BTA_AV_RC_HANDLE_NONE) {
@@ -1805,7 +1774,7 @@
(uint8_t)(p_scb->hdi + 1), p_lcb->lidx);
p_cb->rcb[rc_handle].peer_features = peer_features;
} else {
- APPL_TRACE_ERROR("can not find LCB!!");
+ APPL_TRACE_ERROR("%s: can not find LCB!!", __func__);
}
} else if (p_scb->use_rc) {
/* can not find AVRC on peer device. report failure */
@@ -1861,16 +1830,17 @@
rc_close.rc_handle = BTA_AV_RC_HANDLE_NONE;
p_scb = NULL;
- APPL_TRACE_DEBUG("bta_av_rc_closed rc_handle:%d", p_msg->handle);
+ APPL_TRACE_DEBUG("%s: rc_handle:%d", __func__, p_msg->handle);
for (i = 0; i < BTA_AV_NUM_RCB; i++) {
p_rcb = &p_cb->rcb[i];
- APPL_TRACE_DEBUG("bta_av_rc_closed rcb[%d] rc_handle:%d, status=0x%x", i,
+ APPL_TRACE_DEBUG("%s: rcb[%d] rc_handle:%d, status=0x%x", __func__, i,
p_rcb->handle, p_rcb->status);
if (p_rcb->handle == p_msg->handle) {
rc_close.rc_handle = i;
p_rcb->status &= ~BTA_AV_RC_CONN_MASK;
p_rcb->peer_features = 0;
- APPL_TRACE_DEBUG(" shdl:%d, lidx:%d", p_rcb->shdl, p_rcb->lidx);
+ APPL_TRACE_DEBUG("%s: shdl:%d, lidx:%d", __func__, p_rcb->shdl,
+ p_rcb->lidx);
if (p_rcb->shdl) {
if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) {
p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
@@ -1879,14 +1849,16 @@
rc_close.peer_addr = p_scb->peer_addr;
if (p_scb->rc_handle == p_rcb->handle)
p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
- APPL_TRACE_DEBUG("shdl:%d, srch:%d", p_rcb->shdl, p_scb->rc_handle);
+ APPL_TRACE_DEBUG("%s: shdl:%d, srch:%d", __func__, p_rcb->shdl,
+ p_scb->rc_handle);
}
p_rcb->shdl = 0;
} else if (p_rcb->lidx == (BTA_AV_NUM_LINKS + 1)) {
/* if the RCB uses the extra LCB, use the addr for event and clean it */
p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
rc_close.peer_addr = p_msg->peer_addr;
- VLOG(1) << "rc_only closed bd_addr:" << p_msg->peer_addr;
+ LOG_INFO(LOG_TAG, "%s: rc_only closed bd_addr: %s", __func__,
+ p_msg->peer_addr.ToString().c_str());
p_lcb->conn_msk = 0;
p_lcb->lidx = 0;
}
@@ -1940,8 +1912,8 @@
tBTA_AV_RC_CONN_CHG* p_msg = (tBTA_AV_RC_CONN_CHG*)p_data;
tBTA_AV_RC_BROWSE_OPEN rc_browse_open;
- VLOG(1) << "bta_av_rc_browse_opened bd_addr:" << p_msg->peer_addr;
- APPL_TRACE_DEBUG("bta_av_rc_browse_opened rc_handle:%d", p_msg->handle);
+ LOG_INFO(LOG_TAG, "%s: peer_addr: %s rc_handle:%d", __func__,
+ p_msg->peer_addr.ToString().c_str(), p_msg->handle);
rc_browse_open.status = BTA_AV_SUCCESS;
rc_browse_open.rc_handle = p_msg->handle;
@@ -1966,8 +1938,8 @@
tBTA_AV_RC_CONN_CHG* p_msg = (tBTA_AV_RC_CONN_CHG*)p_data;
tBTA_AV_RC_BROWSE_CLOSE rc_browse_close;
- VLOG(1) << "bta_av_rc_browse_closed bd_addr:" << p_msg->peer_addr;
- APPL_TRACE_DEBUG("bta_av_rc_browse_closed rc_handle:%d", p_msg->handle);
+ LOG_INFO(LOG_TAG, "%s: peer_addr: %s rc_handle:%d", __func__,
+ p_msg->peer_addr.ToString().c_str(), p_msg->handle);
rc_browse_close.rc_handle = p_msg->handle;
rc_browse_close.peer_addr = p_msg->peer_addr;
@@ -1997,7 +1969,8 @@
RawAddress* p_addr = NULL;
uint8_t rc_handle;
- APPL_TRACE_DEBUG("bta_av_rc_disc 0x%x, %d", disc, bta_av_cb.disc);
+ APPL_TRACE_DEBUG("%s: disc: 0x%x, bta_av_cb.disc: 0x%x", __func__, disc,
+ bta_av_cb.disc);
if ((bta_av_cb.disc != 0) || (disc == 0)) return;
if ((disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK) {
@@ -2011,7 +1984,7 @@
p_scb = p_cb->p_scb[hdi];
if (p_scb) {
- APPL_TRACE_DEBUG("rc_handle %d", p_scb->rc_handle);
+ APPL_TRACE_DEBUG("%s: rc_handle %d", __func__, p_scb->rc_handle);
p_addr = &p_scb->peer_addr;
}
}
@@ -2031,7 +2004,7 @@
if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, *p_addr, &db_params,
bta_av_avrc_sdp_cback) == AVRC_SUCCESS) {
p_cb->disc = disc;
- APPL_TRACE_DEBUG("disc %d", p_cb->disc);
+ APPL_TRACE_DEBUG("%s: disc 0x%x", __func__, p_cb->disc);
}
}
}
@@ -2056,51 +2029,43 @@
p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
if (p_scb) {
- APPL_TRACE_DEBUG("deregistered %d(h%d)", p_scb->chnl, p_scb->hndl);
+ APPL_TRACE_DEBUG("%s: deregistered %d(h%d)", __func__, p_scb->chnl,
+ p_scb->hndl);
mask = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- p_cb->reg_audio &= ~mask;
- if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt) {
- /* this channel is still marked as open. decrease the count */
- bta_av_cb.audio_open_cnt--;
- }
- p_cb->conn_audio &= ~mask;
+ p_cb->reg_audio &= ~mask;
+ if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt) {
+ /* this channel is still marked as open. decrease the count */
+ bta_av_cb.audio_open_cnt--;
+ }
+ p_cb->conn_audio &= ~mask;
- if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM && p_scb->a2dp_list) {
- /* make sure no buffers are in a2dp_list */
- while (!list_is_empty(p_scb->a2dp_list)) {
- p_buf = (BT_HDR*)list_front(p_scb->a2dp_list);
- list_remove(p_scb->a2dp_list, p_buf);
- osi_free(p_buf);
- }
+ if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM && p_scb->a2dp_list) {
+ /* make sure no buffers are in a2dp_list */
+ while (!list_is_empty(p_scb->a2dp_list)) {
+ p_buf = (BT_HDR*)list_front(p_scb->a2dp_list);
+ list_remove(p_scb->a2dp_list, p_buf);
+ osi_free(p_buf);
}
+ }
- /* remove the A2DP SDP record, if no more audio stream is left */
- if (!p_cb->reg_audio) {
+ /* remove the A2DP SDP record, if no more audio stream is left */
+ if (!p_cb->reg_audio) {
#if (BTA_AR_INCLUDED == TRUE)
- bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, BTA_ID_AV);
+ bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, BTA_ID_AV);
#endif
- if (p_cb->sdp_a2dp_handle) {
- bta_av_del_sdp_rec(&p_cb->sdp_a2dp_handle);
- p_cb->sdp_a2dp_handle = 0;
- bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
- }
+ if (p_cb->sdp_a2dp_handle) {
+ bta_av_del_sdp_rec(&p_cb->sdp_a2dp_handle);
+ p_cb->sdp_a2dp_handle = 0;
+ bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+ }
#if (BTA_AV_SINK_INCLUDED == TRUE)
- if (p_cb->sdp_a2dp_snk_handle) {
- bta_av_del_sdp_rec(&p_cb->sdp_a2dp_snk_handle);
- p_cb->sdp_a2dp_snk_handle = 0;
- bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);
- }
-#endif
+ if (p_cb->sdp_a2dp_snk_handle) {
+ bta_av_del_sdp_rec(&p_cb->sdp_a2dp_snk_handle);
+ p_cb->sdp_a2dp_snk_handle = 0;
+ bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);
}
- } else {
- p_cb->reg_video &= ~mask;
- /* make sure that this channel is not connected */
- p_cb->conn_video &= ~mask;
- /* remove the VDP SDP record, (only one video stream at most) */
- bta_av_del_sdp_rec(&p_cb->sdp_vdp_handle);
- bta_sys_remove_uuid(UUID_SERVCLASS_VIDEO_SOURCE);
+#endif
}
/* make sure that the timer is not active */
@@ -2108,10 +2073,10 @@
osi_free_and_reset((void**)&p_cb->p_scb[p_scb->hdi]);
}
- APPL_TRACE_DEBUG("audio 0x%x, video: 0x%x, disable:%d", p_cb->reg_audio,
- p_cb->reg_video, p_cb->disabling);
+ APPL_TRACE_DEBUG("%s: audio 0x%x, disable:%d", __func__, p_cb->reg_audio,
+ p_cb->disabling);
/* if no stream control block is active */
- if ((p_cb->reg_audio + p_cb->reg_video) == 0) {
+ if (p_cb->reg_audio == 0) {
#if (BTA_AR_INCLUDED == TRUE)
/* deregister from AVDT */
bta_ar_dereg_avdt(BTA_ID_AV);
diff --git a/bta/av/bta_av_api.cc b/bta/av/bta_av_api.cc
index a8e379a..73ffc8d 100644
--- a/bta/av/bta_av_api.cc
+++ b/bta/av/bta_av_api.cc
@@ -153,6 +153,10 @@
******************************************************************************/
void BTA_AvOpen(const RawAddress& bd_addr, tBTA_AV_HNDL handle, bool use_rc,
tBTA_SEC sec_mask, uint16_t uuid) {
+ APPL_TRACE_DEBUG("%s: peer %s handle:0x%x use_rc=%s sec_mask=0x%x uuid=0x%x",
+ __func__, bd_addr.ToString().c_str(), handle,
+ (use_rc) ? "true" : "false", sec_mask, uuid)
+
tBTA_AV_API_OPEN* p_buf =
(tBTA_AV_API_OPEN*)osi_malloc(sizeof(tBTA_AV_API_OPEN));
@@ -177,6 +181,8 @@
*
******************************************************************************/
void BTA_AvClose(tBTA_AV_HNDL handle) {
+ APPL_TRACE_DEBUG("%s: handle:0x%x", __func__, handle);
+
BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
p_buf->event = BTA_AV_API_CLOSE_EVT;
@@ -213,10 +219,11 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStart(void) {
+void BTA_AvStart(tBTA_AV_HNDL handle) {
BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
p_buf->event = BTA_AV_API_START_EVT;
+ p_buf->layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
@@ -270,11 +277,12 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStop(bool suspend) {
+void BTA_AvStop(tBTA_AV_HNDL handle, bool suspend) {
tBTA_AV_API_STOP* p_buf =
(tBTA_AV_API_STOP*)osi_malloc(sizeof(tBTA_AV_API_STOP));
p_buf->hdr.event = BTA_AV_API_STOP_EVT;
+ p_buf->hdr.layer_specific = handle;
p_buf->flush = true;
p_buf->suspend = suspend;
p_buf->reconfig_stop = false;
diff --git a/bta/av/bta_av_cfg.cc b/bta/av/bta_av_cfg.cc
index ee4ccb7..76c9454 100644
--- a/bta/av/bta_av_cfg.cc
+++ b/bta/av/bta_av_cfg.cc
@@ -128,19 +128,16 @@
/* This configuration to be used when we are Src + TG + CT( only for abs vol) */
const tBTA_AV_CFG bta_av_cfg = {
- BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
- 512, /* AVRCP MTU at L2CAP for control channel */
- BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
+ BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
+ 512, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
BTA_AV_RC_SUPF_TG, /* AVRCP target categories */
672, /* AVDTP signaling channel MTU at L2CAP */
- BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP
- */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
bta_av_audio_flush_to, /* AVDTP audio transport channel flush
timeout */
6, /* AVDTP audio channel max data queue size */
- BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
- 600, /* AVDTP video transport channel flush timeout */
false, /* true, to accept AVRC 1.3 group nevigation command */
2, /* company id count in p_meta_co_ids */
BTA_AV_NUM_RC_EVT_IDS, /* event id count in p_meta_evt_ids */
@@ -150,8 +147,7 @@
for company id */
bta_av_meta_caps_evt_ids, /* the the metadata Get Capabilities
response for event id */
- NULL, /* the action function table for VDP stream */
- NULL, /* action function to register VDP */
+ NULL, /* the action function table for audio stream */
BTA_AV_RC_CT_NAME, /* Default AVRCP controller name */
BTA_AV_RC_TG_NAME /* Default AVRCP target name */
};
@@ -159,19 +155,15 @@
/* This configuration to be used when we are Sink + CT + TG( only for abs vol)
*/
const tBTA_AV_CFG bta_avk_cfg = {
- AVRC_CO_METADATA, /* AVRCP Company ID */
- 512, /* AVRCP MTU at L2CAP for control channel */
+ AVRC_CO_METADATA, /* AVRCP Company ID */
+ 512, /* AVRCP MTU at L2CAP for control channel */
BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
BTA_AVK_RC_SUPF_CT, /* AVRCP controller categories */
BTA_AVK_RC_SUPF_TG, /* AVRCP target categories */
672, /* AVDTP signaling channel MTU at L2CAP */
- BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP
- */
- bta_av_audio_flush_to, /* AVDTP audio transport channel flush
- timeout */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
+ bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
6, /* AVDTP audio channel max data queue size */
- BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
- 600, /* AVDTP video transport channel flush timeout */
false, /* true, to accept AVRC 1.3 group nevigation command */
2, /* company id count in p_meta_co_ids */
BTA_AVK_NUM_RC_EVT_IDS, /* event id count in p_meta_evt_ids */
@@ -181,39 +173,33 @@
for company id */
bta_avk_meta_caps_evt_ids, /* the the metadata Get Capabilities
response for event id */
- NULL, /* the action function table for VDP stream */
- NULL, /* action function to register VDP */
+ NULL, /* the action function table for audio stream */
{0}, /* Default AVRCP controller name */
{0}, /* Default AVRCP target name */
};
/* This configuration to be used when we are using AVRCP1.3 */
const tBTA_AV_CFG bta_av_cfg_compatibility = {
- BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
- 512, /* AVRCP MTU at L2CAP for control channel */
- BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
- BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
- AVRC_SUPF_TG_CAT1, /* Only support CAT1 for AVRCP1.3 */
- 672, /* AVDTP signaling channel MTU at L2CAP */
- BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP
- */
- bta_av_audio_flush_to, /* AVDTP audio transport channel flush
- timeout */
- 6, /* AVDTP audio channel max data queue size */
- BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
- 600, /* AVDTP video transport channel flush timeout */
- false, /* true, to accept AVRC 1.3 group nevigation command */
- 2, /* company id count in p_meta_co_ids */
- BTA_AV_NUM_RC_EVT_IDS_AVRCP13, /* event id count for AVRCP1.3*/
+ BTA_AV_RC_COMP_ID, /* AVRCP Company ID */
+ 512, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
+ BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
+ AVRC_SUPF_TG_CAT1, /* Only support CAT1 for AVRCP1.3 */
+ 672, /* AVDTP signaling channel MTU at L2CAP */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
+ bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
+ 6, /* AVDTP audio channel max data queue size */
+ false, /* true, to accept AVRC 1.3 group nevigation command */
+ 2, /* company id count in p_meta_co_ids */
+ BTA_AV_NUM_RC_EVT_IDS_AVRCP13, /* event id count for AVRCP1.3 */
BTA_AV_RC_PASS_RSP_CODE, /* the default response code for pass
through commands */
bta_av_meta_caps_co_ids, /* the metadata Get Capabilities response
for company id */
bta_av_meta_caps_evt_ids_avrcp13, /* the the metadata Get Capabilities
response for event id, compatible
- with AVRCP1.3*/
- NULL, /* the action function table for VDP stream */
- NULL, /* action function to register VDP */
+ with AVRCP1.3 */
+ NULL, /* the action function table for audio stream */
BTA_AV_RC_CT_NAME, /* Default AVRCP controller name */
BTA_AV_RC_TG_NAME /* Default AVRCP target name */
};
diff --git a/bta/av/bta_av_ci.cc b/bta/av/bta_av_ci.cc
index 64d24d7..a3d552d 100644
--- a/bta/av/bta_av_ci.cc
+++ b/bta/av/bta_av_ci.cc
@@ -23,6 +23,10 @@
*
******************************************************************************/
+#define LOG_TAG "bt_bta_av"
+
+#include "osi/include/log.h"
+
#include "bta_av_ci.h"
#include "bta_api.h"
#include "bta_av_int.h"
@@ -36,7 +40,7 @@
*
* Description This function sends an event to the AV indicating that
* the phone has audio stream data ready to send and AV
- * should call bta_av_co_audio_src_data_path().
+ * should call bta_av_co_audio_source_data_path().
*
* Returns void
*
@@ -63,13 +67,19 @@
* Returns void
*
******************************************************************************/
-void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, uint8_t err_code, uint8_t category,
- uint8_t num_seid, uint8_t* p_seid, bool recfg_needed,
- uint8_t avdt_handle) {
+void bta_av_ci_setconfig(tBTA_AV_HNDL bta_av_handle, uint8_t err_code,
+ uint8_t category, uint8_t num_seid, uint8_t* p_seid,
+ bool recfg_needed, uint8_t avdt_handle) {
+ LOG_DEBUG(LOG_TAG,
+ "%s: bta_av_handle=%d err_code=%d category=%d "
+ "num_seid=%d recfg_needed=%s avdt_handle=%d",
+ __func__, bta_av_handle, err_code, category, num_seid,
+ recfg_needed ? "true" : "false", avdt_handle);
+
tBTA_AV_CI_SETCONFIG* p_buf =
(tBTA_AV_CI_SETCONFIG*)osi_malloc(sizeof(tBTA_AV_CI_SETCONFIG));
- p_buf->hdr.layer_specific = hndl;
+ p_buf->hdr.layer_specific = bta_av_handle;
p_buf->hdr.event = (err_code == A2DP_SUCCESS) ? BTA_AV_CI_SETCONFIG_OK_EVT
: BTA_AV_CI_SETCONFIG_FAIL_EVT;
p_buf->err_code = err_code;
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
index e99c4bd..e97321d 100644
--- a/bta/av/bta_av_int.h
+++ b/bta/av/bta_av_int.h
@@ -156,30 +156,40 @@
/* function types for call-out functions */
typedef bool (*tBTA_AV_CO_INIT)(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
-typedef void (*tBTA_AV_CO_DISC_RES)(tBTA_AV_HNDL hndl, uint8_t num_seps,
- uint8_t num_snk, uint8_t num_src,
- const RawAddress& addr,
- uint16_t uuid_local);
-typedef tA2DP_STATUS (*tBTA_AV_CO_GETCFG)(tBTA_AV_HNDL hndl,
+ AvdtpSepConfig* p_cfg);
+typedef void (*tBTA_AV_CO_DISC_RES)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
+ uint8_t num_seps, uint8_t num_snk,
+ uint8_t num_src, uint16_t uuid_local);
+typedef tA2DP_STATUS (*tBTA_AV_CO_GETCFG)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
uint8_t* p_codec_info,
uint8_t* p_sep_info_idx, uint8_t seid,
uint8_t* p_num_protect,
uint8_t* p_protect_info);
-typedef void (*tBTA_AV_CO_SETCFG)(tBTA_AV_HNDL hndl,
+typedef void (*tBTA_AV_CO_SETCFG)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
const uint8_t* p_codec_info, uint8_t seid,
- const RawAddress& addr, uint8_t num_protect,
+ uint8_t num_protect,
const uint8_t* p_protect_info,
uint8_t t_local_sep, uint8_t avdt_handle);
-typedef void (*tBTA_AV_CO_OPEN)(tBTA_AV_HNDL hndl, uint16_t mtu);
-typedef void (*tBTA_AV_CO_CLOSE)(tBTA_AV_HNDL hndl);
-typedef void (*tBTA_AV_CO_START)(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
- bool* p_no_rtp_hdr);
-typedef void (*tBTA_AV_CO_STOP)(tBTA_AV_HNDL hndl);
-typedef void* (*tBTA_AV_CO_DATAPATH)(const uint8_t* p_codec_info,
- uint32_t* p_timestamp);
-typedef void (*tBTA_AV_CO_DELAY)(tBTA_AV_HNDL hndl, uint16_t delay);
-typedef void (*tBTA_AV_CO_UPDATE_MTU)(tBTA_AV_HNDL hndl, uint16_t mtu);
+typedef void (*tBTA_AV_CO_OPEN)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr, uint16_t mtu);
+typedef void (*tBTA_AV_CO_CLOSE)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr);
+typedef void (*tBTA_AV_CO_START)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
+ const uint8_t* p_codec_info,
+ bool* p_no_rtp_header);
+typedef void (*tBTA_AV_CO_STOP)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr);
+typedef BT_HDR* (*tBTA_AV_CO_DATAPATH)(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp);
+typedef void (*tBTA_AV_CO_DELAY)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr, uint16_t delay);
+typedef void (*tBTA_AV_CO_UPDATE_MTU)(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_addr,
+ uint16_t mtu);
/* the call-out functions for one stream */
typedef struct {
@@ -313,9 +323,10 @@
/* data type for all stream events from AVDTP */
typedef struct {
BT_HDR hdr;
- tAVDT_CFG cfg; /* configuration/capabilities parameters */
+ AvdtpSepConfig cfg; /* configuration/capabilities parameters */
tAVDT_CTRL msg; /* AVDTP callback message parameters */
RawAddress bd_addr; /* bd address */
+ uint8_t scb_index;
uint8_t handle;
uint8_t avdt_event;
bool initiator; /* true, if local device initiates the SUSPEND */
@@ -446,11 +457,11 @@
const tBTA_AV_CO_FUNCTS* p_cos; /* the associated callout functions */
bool sdp_discovery_started; /* variable to determine whether SDP is started */
tBTA_AV_SEP seps[BTAV_A2DP_CODEC_INDEX_MAX];
- tAVDT_CFG peer_cap; /* buffer used for get capabilities */
+ AvdtpSepConfig peer_cap; /* buffer used for get capabilities */
list_t* a2dp_list; /* used for audio channels only */
tBTA_AV_Q_INFO q_info;
tAVDT_SEP_INFO sep_info[BTA_AV_NUM_SEPS]; /* stream discovery results */
- tAVDT_CFG cfg; /* local SEP configuration */
+ AvdtpSepConfig cfg; /* local SEP configuration */
alarm_t* avrc_ct_timer; /* delay timer for AVRC CT */
RawAddress peer_addr; /* peer BD address */
uint16_t l2c_cid; /* L2CAP channel ID */
@@ -488,13 +499,13 @@
successfull, else False if command fails */
bool suspend_sup; /* true if Suspend stream is supported, else false if
suspend command fails */
- bool deregistring; /* true if deregistering */
+ bool deregistering; /* true if deregistering */
bool sco_suspend; /* true if SUSPEND is issued automatically for SCO */
uint8_t coll_mask; /* Mask to check incoming and outgoing collision */
tBTA_AV_API_OPEN open_api; /* Saved OPEN api message */
uint8_t wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */
uint8_t q_tag; /* identify the associated q_info union member */
- bool no_rtp_hdr; /* true if add no RTP header*/
+ bool no_rtp_header; /* true if add no RTP header */
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 */
@@ -541,7 +552,6 @@
accept_signalling_timer; /* timer to monitor signalling when accepting */
uint32_t sdp_a2dp_handle; /* SDP record handle for audio src */
uint32_t sdp_a2dp_snk_handle; /* SDP record handle for audio snk */
- uint32_t sdp_vdp_handle; /* SDP record handle for video src */
tBTA_AV_FEAT features; /* features mask */
tBTA_SEC sec_mask; /* security mask */
tBTA_AV_HNDL handle; /* the handle for SDP activity */
@@ -549,19 +559,15 @@
uint8_t
disc; /* (hdi+1) or (rc_handle|BTA_AV_CHNL_MSK) if p_disc_db is in use */
uint8_t state; /* state machine state */
- uint8_t conn_rc; /* handle mask of connected RCP channels */
uint8_t conn_audio; /* handle mask of connected audio channels */
- uint8_t conn_video; /* handle mask of connected video channels */
uint8_t conn_lcb; /* index mask of used LCBs */
uint8_t audio_open_cnt; /* number of connected audio channels */
uint8_t reg_audio; /* handle mask of registered audio channels */
- uint8_t reg_video; /* handle mask of registered video channels */
uint8_t rc_acp_handle;
uint8_t rc_acp_idx; /* (index + 1) to RCB */
uint8_t rs_idx; /* (index + 1) to SCB for the one waiting for RS on open */
bool sco_occupied; /* true if SCO is being used or call is in progress */
uint8_t audio_streams; /* handle mask of streaming audio channels */
- uint8_t video_streams; /* handle mask of streaming video channels */
} tBTA_AV_CB;
/*****************************************************************************
@@ -583,7 +589,6 @@
extern const tBTA_AV_SACT bta_av_a2dp_action[];
extern const tBTA_AV_CO_FUNCTS bta_av_a2dp_cos;
-extern tAVDT_CTRL_CBACK* const bta_av_dt_cback[];
extern void bta_av_sink_data_cback(uint8_t handle, BT_HDR* p_pkt,
uint32_t time_stamp, uint8_t m_pt);
@@ -595,8 +600,9 @@
extern bool bta_av_chk_start(tBTA_AV_SCB* p_scb);
extern void bta_av_restore_switch(void);
extern uint16_t bta_av_chk_mtu(tBTA_AV_SCB* p_scb, uint16_t mtu);
-extern void bta_av_conn_cback(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
+extern void bta_av_conn_cback(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index);
extern uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl,
uint8_t lidx);
extern void bta_av_stream_chg(tBTA_AV_SCB* p_scb, bool started);
@@ -606,6 +612,7 @@
extern bool bta_av_is_scb_init(tBTA_AV_SCB* p_scb);
extern void bta_av_set_scb_sst_incoming(tBTA_AV_SCB* p_scb);
extern tBTA_AV_LCB* bta_av_find_lcb(const RawAddress& addr, uint8_t op);
+extern const char* bta_av_sst_code(uint8_t state);
/* main functions */
extern void bta_av_api_deregister(tBTA_AV_DATA* p_data);
@@ -646,6 +653,10 @@
extern tBTA_AV_RCB* bta_av_get_rcb_by_shdl(uint8_t shdl);
extern void bta_av_del_rc(tBTA_AV_RCB* p_rcb);
+extern void bta_av_proc_stream_evt(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index);
+
/* ssm action functions */
extern void bta_av_do_disc_a2dp(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
extern void bta_av_cleanup(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data);
diff --git a/bta/av/bta_av_main.cc b/bta/av/bta_av_main.cc
index f941865..e35e349 100644
--- a/bta/av/bta_av_main.cc
+++ b/bta/av/bta_av_main.cc
@@ -304,49 +304,32 @@
*
******************************************************************************/
static tBTA_AV_SCB* bta_av_alloc_scb(tBTA_AV_CHNL chnl) {
- tBTA_AV_SCB* p_ret = NULL;
- int xx;
- tBTA_AV_STATUS sts = BTA_AV_SUCCESS;
-
- if (chnl == BTA_AV_CHNL_VIDEO) {
- if (p_bta_av_cfg->p_act_tbl == NULL || p_bta_av_cfg->p_reg == NULL) {
- APPL_TRACE_ERROR("Video streaming not supported");
- sts = BTA_AV_FAIL;
- } else {
- /* allow only one Video channel */
- if (bta_av_cb.reg_video) {
- APPL_TRACE_ERROR("Already registered");
- sts = BTA_AV_FAIL;
- }
- }
- } else if (chnl != BTA_AV_CHNL_AUDIO) {
- APPL_TRACE_ERROR("bad channel: %d", chnl);
- sts = BTA_AV_FAIL;
+ if (chnl != BTA_AV_CHNL_AUDIO) {
+ APPL_TRACE_ERROR("%s: bad channel: %d", __func__, chnl);
+ return nullptr;
}
- if (sts == BTA_AV_SUCCESS) {
- for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
- if (bta_av_cb.p_scb[xx] == NULL) {
- /* found an empty spot */
- p_ret = (tBTA_AV_SCB*)osi_calloc(sizeof(tBTA_AV_SCB));
- p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
- p_ret->chnl = chnl;
- p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
- p_ret->hdi = xx;
- p_ret->a2dp_list = list_new(NULL);
- p_ret->avrc_ct_timer = alarm_new("bta_av.avrc_ct_timer");
- bta_av_cb.p_scb[xx] = p_ret;
- break;
- }
- }
+ for (int xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
+ if (bta_av_cb.p_scb[xx] != nullptr) continue;
+ // Found an empty spot
+ tBTA_AV_SCB* p_ret = (tBTA_AV_SCB*)osi_calloc(sizeof(tBTA_AV_SCB));
+ p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
+ p_ret->chnl = chnl;
+ p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
+ p_ret->hdi = xx;
+ p_ret->a2dp_list = list_new(nullptr);
+ p_ret->avrc_ct_timer = alarm_new("bta_av.avrc_ct_timer");
+ bta_av_cb.p_scb[xx] = p_ret;
+ return p_ret;
}
- return p_ret;
+
+ return nullptr;
}
/*******************************************************************************
******************************************************************************/
-void bta_av_conn_cback(UNUSED_ATTR uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data) {
+void bta_av_conn_cback(UNUSED_ATTR uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data, uint8_t scb_index) {
uint16_t evt = 0;
tBTA_AV_SCB* p_scb = NULL;
@@ -359,7 +342,7 @@
{
evt = BTA_AV_SIG_CHG_EVT;
if (event == AVDT_DISCONNECT_IND_EVT) {
- p_scb = bta_av_addr_to_scb(*bd_addr);
+ p_scb = bta_av_addr_to_scb(bd_addr);
} else if (event == AVDT_CONNECT_IND_EVT) {
APPL_TRACE_DEBUG("%s: CONN_IND is ACP:%d", __func__,
p_data->hdr.err_param);
@@ -370,11 +353,14 @@
p_msg->hdr.event = evt;
p_msg->hdr.layer_specific = event;
p_msg->hdr.offset = p_data->hdr.err_param;
- p_msg->bd_addr = *bd_addr;
+ p_msg->bd_addr = bd_addr;
+ p_msg->scb_index = scb_index;
if (p_scb) {
- APPL_TRACE_DEBUG("scb hndl x%x, role x%x", p_scb->hndl, p_scb->role);
+ APPL_TRACE_DEBUG("%s: scb hndl x%x, role x%x", __func__, p_scb->hndl,
+ p_scb->role);
}
- VLOG(1) << "conn_cback bd_addr:" << bd_addr;
+ LOG_INFO(LOG_TAG, "%s: conn_cback bd_addr: %s", __func__,
+ bd_addr.ToString().c_str());
bta_sys_sendmsg(p_msg);
}
}
@@ -409,12 +395,12 @@
static void bta_av_api_register(tBTA_AV_DATA* p_data) {
tBTA_AV_REGISTER registr;
tBTA_AV_SCB* p_scb; /* stream control block */
- tAVDT_REG reg;
- tAVDT_CS cs;
+ AvdtpRcb reg;
+ AvdtpStreamConfig avdtp_stream_config;
char* p_service_name;
tBTA_UTL_COD cod;
- memset(&cs, 0, sizeof(tAVDT_CS));
+ avdtp_stream_config.Reset();
registr.status = BTA_AV_FAIL_RESOURCES;
registr.app_id = p_data->api_reg.app_id;
@@ -422,7 +408,8 @@
char avrcp_version[PROPERTY_VALUE_MAX] = {0};
osi_property_get(AVRCP_VERSION_PROPERTY, avrcp_version, AVRCP_1_4_STRING);
- LOG_INFO(LOG_TAG, "AVRCP version used for sdp: \"%s\"", avrcp_version);
+ LOG_INFO(LOG_TAG, "%s: AVRCP version used for sdp: \"%s\"", __func__,
+ avrcp_version);
uint16_t profile_initialized = p_data->api_reg.service_uuid;
if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
@@ -431,21 +418,21 @@
p_bta_av_cfg = &bta_av_cfg;
if (!strncmp(AVRCP_1_3_STRING, avrcp_version, sizeof(AVRCP_1_3_STRING))) {
- LOG_INFO(LOG_TAG, "AVRCP 1.3 capabilites used");
+ LOG_INFO(LOG_TAG, "%s: AVRCP 1.3 capabilites used", __func__);
p_bta_av_cfg = &bta_av_cfg_compatibility;
}
}
APPL_TRACE_DEBUG("%s: profile: 0x%x", __func__, profile_initialized);
if (p_bta_av_cfg == NULL) {
- APPL_TRACE_ERROR("AV configuration is null!");
+ APPL_TRACE_ERROR("%s: AV configuration is null!", __func__);
return;
}
do {
p_scb = bta_av_alloc_scb(registr.chnl);
if (p_scb == NULL) {
- APPL_TRACE_ERROR("failed to alloc SCB");
+ APPL_TRACE_ERROR("%s: failed to alloc SCB", __func__);
break;
}
@@ -455,13 +442,14 @@
/* initialize the stream control block */
registr.status = BTA_AV_SUCCESS;
- if ((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0) {
+ if (bta_av_cb.reg_audio == 0) {
/* the first channel registered. register to AVDTP */
reg.ctrl_mtu = p_bta_av_cfg->sig_mtu;
reg.ret_tout = BTA_AV_RET_TOUT;
reg.sig_tout = BTA_AV_SIG_TOUT;
reg.idle_tout = BTA_AV_IDLE_TOUT;
reg.sec_mask = bta_av_cb.sec_mask;
+ reg.scb_index = p_scb->hdi;
#if (BTA_AR_INCLUDED == TRUE)
bta_ar_reg_avdt(®, bta_av_conn_cback, BTA_ID_AV);
#endif
@@ -519,11 +507,13 @@
} /* if 1st channel */
/* get stream configuration and create stream */
- cs.cfg.num_codec = 1;
- cs.nsc_mask =
- AVDT_NSC_RECONFIG |
- ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY);
- APPL_TRACE_DEBUG("nsc_mask: 0x%x", cs.nsc_mask);
+ avdtp_stream_config.cfg.num_codec = 1;
+ avdtp_stream_config.nsc_mask = AvdtpStreamConfig::AVDT_NSC_RECONFIG;
+ if (!(bta_av_cb.features & BTA_AV_FEAT_PROTECT)) {
+ avdtp_stream_config.nsc_mask |= AvdtpStreamConfig::AVDT_NSC_SECURITY;
+ }
+ APPL_TRACE_DEBUG("%s: nsc_mask: 0x%x", __func__,
+ avdtp_stream_config.nsc_mask);
if (p_data->api_reg.p_service_name[0] == 0) {
p_service_name = NULL;
@@ -535,140 +525,131 @@
p_scb->recfg_sup = true;
p_scb->skip_sdp = false;
- cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi];
- if (registr.chnl == BTA_AV_CHNL_AUDIO) {
- /* set up the audio stream control block */
- p_scb->p_act_tbl = (const tBTA_AV_ACT*)bta_av_a2dp_action;
- p_scb->p_cos = &bta_av_a2dp_cos;
- p_scb->media_type = AVDT_MEDIA_TYPE_AUDIO;
- cs.cfg.psc_mask = AVDT_PSC_TRANS;
- cs.media_type = AVDT_MEDIA_TYPE_AUDIO;
- cs.mtu = p_bta_av_cfg->audio_mtu;
- cs.flush_to = L2CAP_DEFAULT_FLUSH_TO;
- btav_a2dp_codec_index_t codec_index_min =
- BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
- btav_a2dp_codec_index_t codec_index_max =
- BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
+ avdtp_stream_config.scb_index = p_scb->hdi;
+ avdtp_stream_config.p_avdt_ctrl_cback = &bta_av_proc_stream_evt;
- if (bta_av_cb.features & BTA_AV_FEAT_REPORT) {
- cs.cfg.psc_mask |= AVDT_PSC_REPORT;
- cs.p_report_cback = bta_av_a2dp_report_cback;
+ /* set up the audio stream control block */
+ p_scb->p_act_tbl = (const tBTA_AV_ACT*)bta_av_a2dp_action;
+ p_scb->p_cos = &bta_av_a2dp_cos;
+ p_scb->media_type = AVDT_MEDIA_TYPE_AUDIO;
+ avdtp_stream_config.cfg.psc_mask = AVDT_PSC_TRANS;
+ avdtp_stream_config.media_type = AVDT_MEDIA_TYPE_AUDIO;
+ avdtp_stream_config.mtu = p_bta_av_cfg->audio_mtu;
+ avdtp_stream_config.flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ btav_a2dp_codec_index_t codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
+ btav_a2dp_codec_index_t codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
+
+ if (bta_av_cb.features & BTA_AV_FEAT_REPORT) {
+ avdtp_stream_config.cfg.psc_mask |= AVDT_PSC_REPORT;
+ avdtp_stream_config.p_report_cback = bta_av_a2dp_report_cback;
+ }
+ if (bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT)
+ avdtp_stream_config.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
+
+ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
+ avdtp_stream_config.tsep = AVDT_TSEP_SRC;
+ codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
+ codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
+ } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
+ avdtp_stream_config.tsep = AVDT_TSEP_SNK;
+ avdtp_stream_config.p_sink_data_cback = bta_av_sink_data_cback;
+ codec_index_min = BTAV_A2DP_CODEC_INDEX_SINK_MIN;
+ codec_index_max = BTAV_A2DP_CODEC_INDEX_SINK_MAX;
+ }
+
+ /* Initialize handles to zero */
+ for (int xx = 0; xx < BTAV_A2DP_CODEC_INDEX_MAX; xx++) {
+ p_scb->seps[xx].av_handle = 0;
+ }
+
+ /* keep the configuration in the stream control block */
+ p_scb->cfg = avdtp_stream_config.cfg;
+ for (int i = codec_index_min; i < codec_index_max; i++) {
+ btav_a2dp_codec_index_t codec_index =
+ static_cast<btav_a2dp_codec_index_t>(i);
+ if (!(*bta_av_a2dp_cos.init)(codec_index, &avdtp_stream_config.cfg)) {
+ continue;
}
- if (bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT)
- cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
-
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- cs.tsep = AVDT_TSEP_SRC;
- codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN;
- codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX;
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
- cs.tsep = AVDT_TSEP_SNK;
- cs.p_sink_data_cback = bta_av_sink_data_cback;
- codec_index_min = BTAV_A2DP_CODEC_INDEX_SINK_MIN;
- codec_index_max = BTAV_A2DP_CODEC_INDEX_SINK_MAX;
+ if (AVDT_CreateStream(p_scb->app_id, &p_scb->seps[codec_index].av_handle,
+ avdtp_stream_config) != AVDT_SUCCESS) {
+ continue;
}
-
- /* Initialize handles to zero */
- for (int xx = 0; xx < BTAV_A2DP_CODEC_INDEX_MAX; xx++) {
- p_scb->seps[xx].av_handle = 0;
- }
-
- /* keep the configuration in the stream control block */
- memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
- for (int i = codec_index_min; i < codec_index_max; i++) {
- btav_a2dp_codec_index_t codec_index =
- static_cast<btav_a2dp_codec_index_t>(i);
- if (!(*bta_av_a2dp_cos.init)(codec_index, &cs.cfg)) {
- continue;
- }
- if (AVDT_CreateStream(&p_scb->seps[codec_index].av_handle, &cs) !=
- AVDT_SUCCESS) {
- continue;
- }
- /* Save a copy of the codec */
- memcpy(p_scb->seps[codec_index].codec_info, cs.cfg.codec_info,
- AVDT_CODEC_SIZE);
- p_scb->seps[codec_index].tsep = cs.tsep;
- if (cs.tsep == AVDT_TSEP_SNK) {
- p_scb->seps[codec_index].p_app_sink_data_cback =
- p_data->api_reg.p_app_sink_data_cback;
- } else {
- /* In case of A2DP SOURCE we don't need a callback to
- * handle media packets.
- */
- p_scb->seps[codec_index].p_app_sink_data_cback = NULL;
- }
- }
-
- if (!bta_av_cb.reg_audio) {
- bta_av_cb.sdp_a2dp_handle = 0;
- bta_av_cb.sdp_a2dp_snk_handle = 0;
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- /* create the SDP records on the 1st audio channel */
- bta_av_cb.sdp_a2dp_handle = SDP_CreateRecord();
- A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
- A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_handle);
- bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
-#if (BTA_AV_SINK_INCLUDED == TRUE)
- bta_av_cb.sdp_a2dp_snk_handle = SDP_CreateRecord();
- A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL,
- A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_snk_handle);
- bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
-#endif
- }
- /* start listening when A2DP is registered */
- if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
- bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
-
- /* if the AV and AVK are both supported, it cannot support the CT role
+ /* Save a copy of the codec */
+ memcpy(p_scb->seps[codec_index].codec_info,
+ avdtp_stream_config.cfg.codec_info, AVDT_CODEC_SIZE);
+ p_scb->seps[codec_index].tsep = avdtp_stream_config.tsep;
+ if (avdtp_stream_config.tsep == AVDT_TSEP_SNK) {
+ p_scb->seps[codec_index].p_app_sink_data_cback =
+ p_data->api_reg.p_app_sink_data_cback;
+ } else {
+ /* In case of A2DP SOURCE we don't need a callback to
+ * handle media packets.
*/
- if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) {
- /* if TG is not supported, we need to register to AVCT now */
- if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) {
+ p_scb->seps[codec_index].p_app_sink_data_cback = NULL;
+ }
+ }
+
+ if (!bta_av_cb.reg_audio) {
+ bta_av_cb.sdp_a2dp_handle = 0;
+ bta_av_cb.sdp_a2dp_snk_handle = 0;
+ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
+ /* create the SDP records on the 1st audio channel */
+ bta_av_cb.sdp_a2dp_handle = SDP_CreateRecord();
+ A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
+ A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+ } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
+#if (BTA_AV_SINK_INCLUDED == TRUE)
+ bta_av_cb.sdp_a2dp_snk_handle = SDP_CreateRecord();
+ A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL,
+ A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_snk_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
+#endif
+ }
+ /* start listening when A2DP is registered */
+ if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+
+ /* if the AV and AVK are both supported, it cannot support the CT role
+ */
+ if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) {
+ /* if TG is not supported, we need to register to AVCT now */
+ if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0) {
#if (BTA_AR_INCLUDED == TRUE)
#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
- bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
- bta_av_cb.sec_mask, BTA_ID_AV);
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ bta_av_cb.sec_mask, BTA_ID_AV);
#else
- bta_ar_reg_avct(
- p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
- (uint8_t)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)),
- BTA_ID_AV);
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ (uint8_t)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)),
+ BTA_ID_AV);
#endif
#endif
- bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
- }
-#if (BTA_AR_INCLUDED == TRUE)
- /* create an SDP record as AVRC CT. We create 1.3 for SOURCE
- * because we rely on feature bits being scanned by external
- * devices more than the profile version itself.
- *
- * We create 1.4 for SINK since we support browsing.
- */
- if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
- bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
- p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
- (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
- AVRC_REV_1_3);
- } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
- bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
- p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
- (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
- AVRC_REV_1_6);
- }
-#endif
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
}
+#if (BTA_AR_INCLUDED == TRUE)
+ /* create an SDP record as AVRC CT. We create 1.3 for SOURCE
+ * because we rely on feature bits being scanned by external
+ * devices more than the profile version itself.
+ *
+ * We create 1.4 for SINK since we support browsing.
+ */
+ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
+ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+ p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
+ (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
+ AVRC_REV_1_3);
+ } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
+ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+ p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV,
+ (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
+ AVRC_REV_1_6);
+ }
+#endif
}
- bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio);
- } else {
- bta_av_cb.reg_video = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
- bta_av_cb.sdp_vdp_handle = SDP_CreateRecord();
- /* register the video channel */
- /* no need to verify the function pointer here. it's verified prior */
- (*p_bta_av_cfg->p_reg)(&cs, p_service_name, p_scb);
}
+ bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+ APPL_TRACE_DEBUG("%s: reg_audio: 0x%x", __func__, bta_av_cb.reg_audio);
} while (0);
/* call callback with register event */
@@ -691,7 +672,7 @@
tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
if (p_scb) {
- p_scb->deregistring = true;
+ p_scb->deregistering = true;
bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data);
} else {
bta_av_dereg_comp(p_data);
@@ -745,12 +726,13 @@
*
******************************************************************************/
static void bta_av_api_to_ssm(tBTA_AV_DATA* p_data) {
- int xx;
uint16_t event =
p_data->hdr.event - BTA_AV_FIRST_A2S_API_EVT + BTA_AV_FIRST_A2S_SSM_EVT;
+ tBTA_AV_HNDL handle = p_data->hdr.layer_specific;
+ tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(handle);
- for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
- bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+ if (p_scb != nullptr) {
+ bta_av_ssm_execute(p_scb, event, p_data);
}
}
@@ -760,37 +742,31 @@
*
* Description if this is audio channel, check if more than one audio
* channel is connected & already started.
+ * This function needs to be kept very similar to
+ * bta_av_chk_2nd_start
*
* Returns true, if need api_start
*
******************************************************************************/
bool bta_av_chk_start(tBTA_AV_SCB* p_scb) {
bool start = false;
- tBTA_AV_SCB* p_scbi;
- int i;
- if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
- if ((bta_av_cb.audio_open_cnt >= 2) &&
- ((0 ==
- (p_scb->role & BTA_AV_ROLE_AD_ACP)) || /* Outgoing connection or */
- (bta_av_cb.features &
- BTA_AV_FEAT_ACP_START))) /* auto-starting option */
- {
- /* more than one audio channel is connected */
- /* if this is the 2nd stream as ACP, give INT a chance to issue the START
- * command */
- for (i = 0; i < BTA_AV_NUM_STRS; i++) {
- p_scbi = bta_av_cb.p_scb[i];
- if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started) {
- start = true;
- /* may need to update the flush timeout of this already started stream
- */
- if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
- p_scbi->co_started = bta_av_cb.audio_open_cnt;
- L2CA_SetFlushTimeout(
- p_scbi->peer_addr,
- p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
- }
+ if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2) &&
+ (((p_scb->role & BTA_AV_ROLE_AD_ACP) == 0) || // Outgoing connection or
+ (bta_av_cb.features & BTA_AV_FEAT_ACP_START))) { // Auto-starting option
+ // More than one audio channel is connected.
+ // If this is the 2nd stream as ACP, give INT a chance to issue the START
+ // command.
+ for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
+ tBTA_AV_SCB* p_scbi = bta_av_cb.p_scb[i];
+ if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started) {
+ start = true;
+ // May need to update the flush timeout of this already started stream
+ if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
+ p_scbi->co_started = bta_av_cb.audio_open_cnt;
+ L2CA_SetFlushTimeout(
+ p_scbi->peer_addr,
+ p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
}
}
}
@@ -813,7 +789,7 @@
int i;
uint8_t mask;
- APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio);
+ APPL_TRACE_DEBUG("%s: reg_audio: 0x%x", __func__, bta_av_cb.reg_audio);
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
mask = BTA_AV_HNDL_TO_MSK(i);
if (p_cb->conn_audio == mask) {
@@ -843,7 +819,10 @@
uint8_t cur_role;
uint8_t peer_idx = 0;
- APPL_TRACE_DEBUG("bta_av_sys_rs_cback: %d", bta_av_cb.rs_idx);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s new_role:%d hci_status:0x%x bta_av_cb.rs_idx:%d", __func__,
+ peer_addr.ToString().c_str(), id, app_id, bta_av_cb.rs_idx);
+
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
/* loop through all the SCBs to find matching peer addresses and report the
* role change event */
@@ -852,8 +831,9 @@
if (p_scb && p_scb->peer_addr == peer_addr) {
tBTA_AV_ROLE_RES* p_buf =
(tBTA_AV_ROLE_RES*)osi_malloc(sizeof(tBTA_AV_ROLE_RES));
- APPL_TRACE_DEBUG("new_role:%d, hci_status:x%x hndl: x%x", id, app_id,
- p_scb->hndl);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s found: new_role:%d, hci_status:0x%x hndl:0x%x", __func__,
+ peer_addr.ToString().c_str(), id, app_id, p_scb->hndl);
/*
if ((id != BTM_ROLE_MASTER) && (app_id != HCI_SUCCESS))
{
@@ -886,13 +866,20 @@
p_scb = bta_av_cb.p_scb[bta_av_cb.rs_idx - 1];
}
if (p_scb && p_scb->q_tag == BTA_AV_Q_TAG_OPEN) {
- APPL_TRACE_DEBUG("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d",
- bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
+ APPL_TRACE_DEBUG("%s: peer %s rs_idx:%d, hndl:0x%x q_tag:%d", __func__,
+ p_scb->peer_addr.ToString().c_str(), bta_av_cb.rs_idx,
+ p_scb->hndl, p_scb->q_tag);
- if (HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id)
+ if (HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id) {
p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
- else
+ } else {
+ APPL_TRACE_ERROR(
+ "%s: peer %s (p_scb peer %s) role switch failed: new_role:%d "
+ "hci_status:0x%x",
+ __func__, peer_addr.ToString().c_str(),
+ p_scb->peer_addr.ToString().c_str(), id, app_id);
p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
+ }
/* Continue av open process */
bta_av_do_disc_a2dp(p_scb, (tBTA_AV_DATA*)&(p_scb->q_info.open));
@@ -920,7 +907,7 @@
int i;
tBTA_AV_API_STOP stop;
- APPL_TRACE_DEBUG("bta_av_sco_chg_cback:%d status:%d", id, status);
+ APPL_TRACE_DEBUG("%s: id:%d status:%d", __func__, id, status);
if (id) {
bta_av_cb.sco_occupied = true;
@@ -929,7 +916,7 @@
p_scb = bta_av_cb.p_scb[i];
if (p_scb && p_scb->co_started && (!p_scb->sco_suspend)) {
- APPL_TRACE_DEBUG("suspending scb:%d", i);
+ APPL_TRACE_DEBUG("%s: suspending scb:%d", __func__, i);
/* scb is used and started, not suspended automatically */
p_scb->sco_suspend = true;
stop.flush = false;
@@ -946,7 +933,7 @@
if (p_scb && p_scb->sco_suspend) /* scb is used and suspended for SCO */
{
- APPL_TRACE_DEBUG("starting scb:%d", i);
+ APPL_TRACE_DEBUG("%s: starting scb:%d", __func__, i);
bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
}
}
@@ -974,9 +961,8 @@
for (i = 0; i < BTA_AV_NUM_STRS; i++) {
mask = BTA_AV_HNDL_TO_MSK(i);
p_scbi = bta_av_cb.p_scb[i];
- if (p_scbi && (p_scb->hdi != i) && /* not the original channel */
- ((bta_av_cb.conn_audio & mask) || /* connected audio */
- (bta_av_cb.conn_video & mask))) /* connected video */
+ if (p_scbi && (p_scb->hdi != i) && /* not the original channel */
+ ((bta_av_cb.conn_audio & mask))) /* connected audio */
{
BTM_GetRole(p_scbi->peer_addr, &role);
/* this channel is open - clear the role switch link policy for this link
@@ -1018,7 +1004,8 @@
bool is_ok = true;
if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS) {
- LOG_INFO(LOG_TAG, "%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
+ LOG_INFO(LOG_TAG,
+ "%s: hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
__func__, p_scb->hndl, role, bta_av_cb.conn_audio, bits,
bta_av_cb.features);
if (BTM_ROLE_MASTER != role &&
@@ -1066,15 +1053,15 @@
if ((p_scb != p_scbi) && p_scbi &&
(p_scbi->chnl == BTA_AV_CHNL_AUDIO)) {
mask = BTA_AV_HNDL_TO_MSK(i);
- APPL_TRACE_DEBUG("[%d] mtu: %d, mask:0x%x", i, p_scbi->stream_mtu,
- mask);
+ APPL_TRACE_DEBUG("%s: [%d] mtu: %d, mask:0x%x", __func__, i,
+ p_scbi->stream_mtu, mask);
if (bta_av_cb.conn_audio & mask) {
if (ret_mtu > p_scbi->stream_mtu) ret_mtu = p_scbi->stream_mtu;
}
}
}
}
- APPL_TRACE_DEBUG("bta_av_chk_mtu audio count:%d, conn_audio:0x%x, ret:%d",
+ APPL_TRACE_DEBUG("%s: count:%d, conn_audio:0x%x, ret:%d", __func__,
bta_av_cb.audio_open_cnt, bta_av_cb.conn_audio, ret_mtu);
}
return ret_mtu;
@@ -1111,7 +1098,7 @@
if (list_length(p_scbi->a2dp_list) > p_bta_av_cfg->audio_mqs) {
// Drop the oldest packet
- bta_av_co_audio_drop(p_scbi->hndl);
+ bta_av_co_audio_drop(p_scbi->hndl, p_scbi->peer_addr);
BT_HDR* p_buf_drop = static_cast<BT_HDR*>(list_front(p_scbi->a2dp_list));
list_remove(p_scbi->a2dp_list, p_buf_drop);
osi_free(p_buf_drop);
@@ -1144,12 +1131,13 @@
/* set next state */
p_cb->state = state_table[event][BTA_AV_NEXT_STATE];
- APPL_TRACE_EVENT("next state=%d event offset:%d", p_cb->state, event);
+ APPL_TRACE_EVENT("%s: next state=%d event offset:%d", __func__, p_cb->state,
+ event);
/* execute action functions */
action = state_table[event][BTA_AV_ACTION_COL];
if (action != BTA_AV_IGNORE) {
- APPL_TRACE_EVENT("%s action executed %d", __func__, action);
+ APPL_TRACE_EVENT("%s: action executed %d", __func__, action);
(*bta_av_action[action])(p_cb, p_data);
}
}
@@ -1181,7 +1169,7 @@
/* state machine events */
bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA*)p_msg);
} else {
- APPL_TRACE_VERBOSE("handle=0x%x", p_msg->layer_specific);
+ APPL_TRACE_VERBOSE("%s: handle=0x%x", __func__, p_msg->layer_specific);
/* stream state machine events */
bta_av_ssm_execute(bta_av_hndl_to_scb(p_msg->layer_specific), p_msg->event,
(tBTA_AV_DATA*)p_msg);
@@ -1346,3 +1334,110 @@
return "unknown";
}
}
+
+void bta_debug_av_dump(int fd) {
+ dprintf(fd, "\nBTA AV State:\n");
+ dprintf(fd, " State Machine State: %s\n", bta_av_st_code(bta_av_cb.state));
+ dprintf(fd, " Link signalling timer: %s\n",
+ alarm_is_scheduled(bta_av_cb.link_signalling_timer)
+ ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " Accept signalling timer: %s\n",
+ alarm_is_scheduled(bta_av_cb.accept_signalling_timer)
+ ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " SDP A2DP source handle: %d\n", bta_av_cb.sdp_a2dp_handle);
+ dprintf(fd, " SDP A2DP sink handle: %d\n", bta_av_cb.sdp_a2dp_snk_handle);
+ dprintf(fd, " Features: 0x%x\n", bta_av_cb.features);
+ dprintf(fd, " Security mask: 0x%x\n", bta_av_cb.sec_mask);
+ dprintf(fd, " SDP handle: %d\n", bta_av_cb.handle);
+ dprintf(fd, " Disabling: %s\n", bta_av_cb.disabling ? "true" : "false");
+ dprintf(fd, " SCO occupied: %s\n",
+ bta_av_cb.sco_occupied ? "true" : "false");
+ dprintf(fd, " Connected audio channels: %d\n", bta_av_cb.audio_open_cnt);
+ dprintf(fd, " Connected audio channels mask: 0x%x\n", bta_av_cb.conn_audio);
+ dprintf(fd, " Streaming audio channels mask: 0x%x\n",
+ bta_av_cb.audio_streams);
+ dprintf(fd, " Registered audio channels mask: 0x%x\n", bta_av_cb.reg_audio);
+ dprintf(fd, " Connected LCBs mask: 0x%x\n", bta_av_cb.conn_lcb);
+
+ for (size_t i = 0; i < sizeof(bta_av_cb.lcb) / sizeof(bta_av_cb.lcb[0]);
+ i++) {
+ const tBTA_AV_LCB& lcb = bta_av_cb.lcb[i];
+ dprintf(fd, "\n Link control block: %zu peer: %s\n", i,
+ lcb.addr.ToString().c_str());
+ dprintf(fd, " Connected stream handle mask: 0x%x\n", lcb.conn_msk);
+ dprintf(fd, " Index(+1) to LCB: %d\n", lcb.lidx);
+ }
+ for (size_t i = 0; i < BTA_AV_NUM_STRS; i++) {
+ const tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[i];
+ if (p_scb == nullptr) {
+ continue;
+ }
+ dprintf(fd, "\n BTA ID: %zu peer: %s\n", i,
+ p_scb->peer_addr.ToString().c_str());
+ dprintf(fd, " SDP discovery started: %s\n",
+ p_scb->sdp_discovery_started ? "true" : "false");
+ for (size_t j = 0; j < BTAV_A2DP_CODEC_INDEX_MAX; j++) {
+ const tBTA_AV_SEP& sep = p_scb->seps[j];
+ dprintf(fd, " SEP ID: %zu\n", j);
+ dprintf(fd, " SEP AVDTP handle: %d\n", sep.av_handle);
+ dprintf(fd, " Local SEP type: %d\n", sep.tsep);
+ dprintf(fd, " Codec: %s\n", A2DP_CodecName(sep.codec_info));
+ }
+ dprintf(fd, " BTA info tag: %d\n", p_scb->q_tag);
+ dprintf(fd, " API Open peer: %s\n",
+ p_scb->q_info.open.bd_addr.ToString().c_str());
+ dprintf(fd, " Use AVRCP: %s\n",
+ p_scb->q_info.open.use_rc ? "true" : "false");
+ dprintf(fd, " Security mask: 0x%x\n", p_scb->q_info.open.sec_mask);
+ dprintf(fd, " Switch result: %d\n", p_scb->q_info.open.switch_res);
+ dprintf(fd, " Initiator UUID: 0x%x\n", p_scb->q_info.open.uuid);
+ dprintf(fd, " Saved API Open peer: %s\n",
+ p_scb->open_api.bd_addr.ToString().c_str());
+ dprintf(fd, " Use AVRCP: %s\n",
+ p_scb->open_api.use_rc ? "true" : "false");
+ dprintf(fd, " Security mask: 0x%x\n", p_scb->open_api.sec_mask);
+ dprintf(fd, " Switch result: %d\n", p_scb->open_api.switch_res);
+ dprintf(fd, " Initiator UUID: 0x%x\n", p_scb->open_api.uuid);
+ // TODO: Print p_scb->sep_info[], cfg, avrc_ct_timer, current_codec ?
+ dprintf(fd, " L2CAP Channel ID: %d\n", p_scb->l2c_cid);
+ dprintf(fd, " Stream MTU: %d\n", p_scb->stream_mtu);
+ dprintf(fd, " AVDTP version: 0x%x\n", p_scb->avdt_version);
+ dprintf(fd, " Security mask: 0x%x\n", p_scb->sec_mask);
+ dprintf(fd, " Media type: %d\n", p_scb->media_type);
+ dprintf(fd, " Congested: %s\n", p_scb->cong ? "true" : "false");
+ dprintf(fd, " Open status: %d\n", p_scb->open_status);
+ dprintf(fd, " Channel: %d\n", p_scb->chnl);
+ dprintf(fd, " BTA handle: %d\n", p_scb->hndl);
+ dprintf(fd, " Protocol service capabilities mask: 0x%x\n",
+ p_scb->cur_psc_mask);
+ dprintf(fd, " AVDTP handle: %d\n", p_scb->avdt_handle);
+ dprintf(fd, " Stream control block index: %d\n", p_scb->hdi);
+ dprintf(fd, " State machine state: %s(%d)\n",
+ bta_av_sst_code(p_scb->state), p_scb->state);
+ dprintf(fd, " AVDTP label: 0x%x\n", p_scb->avdt_label);
+ dprintf(fd, " Application ID: %d\n", p_scb->app_id);
+ dprintf(fd, " Role: 0x%x\n", p_scb->role);
+ dprintf(fd, " Queued L2CAP buffers: %d\n", p_scb->l2c_bufs);
+ dprintf(fd, " AVRCP allowed: %s\n", p_scb->use_rc ? "true" : "false");
+ dprintf(fd, " Stream started: %s\n", p_scb->started ? "true" : "false");
+ dprintf(fd, " Stream call-out started: %d\n", p_scb->co_started);
+ dprintf(fd, " AVDTP Reconfig supported: %s\n",
+ p_scb->recfg_sup ? "true" : "false");
+ dprintf(fd, " AVDTP Suspend supported: %s\n",
+ p_scb->suspend_sup ? "true" : "false");
+ dprintf(fd, " Deregistering: %s\n",
+ p_scb->deregistering ? "true" : "false");
+ dprintf(fd, " SCO automatic Suspend: %s\n",
+ p_scb->sco_suspend ? "true" : "false");
+ dprintf(fd, " Incoming/outgoing connection collusion mask: 0x%x\n",
+ p_scb->coll_mask);
+ dprintf(fd, " Wait mask: 0x%x\n", p_scb->wait);
+ dprintf(fd, " Don't use RTP header: %s\n",
+ p_scb->no_rtp_header ? "true" : "false");
+ dprintf(fd, " Intended UUID of Initiator to connect to: 0x%x\n",
+ p_scb->uuid_int);
+ dprintf(fd, " Skip SDP: %s\n", p_scb->skip_sdp ? "true" : "false");
+ }
+}
diff --git a/bta/av/bta_av_ssm.cc b/bta/av/bta_av_ssm.cc
index 79b37b3..afa78cc 100644
--- a/bta/av/bta_av_ssm.cc
+++ b/bta/av/bta_av_ssm.cc
@@ -107,8 +107,8 @@
/* state table for init state */
static const uint8_t bta_av_sst_init[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_DO_DISC, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_CLEANUP, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* API_OPEN_EVT */ {BTA_AV_DO_DISC, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_CLOSE_EVT */ {BTA_AV_CLEANUP, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
@@ -117,8 +117,8 @@
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
@@ -130,179 +130,180 @@
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVDT_DISCONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* AVDT_DELAY_RPT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_INIT_SST}};
/* state table for incoming state */
static const uint8_t bta_av_sst_incoming[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_OPEN_AT_INC, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ,
- BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_OPEN_AT_INC, BTA_AV_SIGNORE,
+ BTA_AV_INCOMING_SST},
+ /* API_CLOSE_EVT */
+ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* CI_SETCONFIG_OK_EVT */ {BTA_AV_SETCONFIG_RSP, BTA_AV_ST_RC_TIMER,
- BTA_AV_INCOMING_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_CLEANUP,
- BTA_AV_INIT_SST},
- /* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_DISC_OK_EVT */ {BTA_AV_DISC_RES_AS_ACP, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_SAVE_CAPS, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* API_RECONFIG_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_RC_OPEN_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* CI_SETCONFIG_OK_EVT */
+ {BTA_AV_SETCONFIG_RSP, BTA_AV_ST_RC_TIMER, BTA_AV_INCOMING_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_CLEANUP, BTA_AV_INIT_SST},
+ /* SDP_DISC_OK_EVT */
+ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* SDP_DISC_FAIL_EVT */
+ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_DISC_OK_EVT */
+ {BTA_AV_DISC_RES_AS_ACP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_SAVE_CAPS, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* STR_OPEN_OK_EVT */ {BTA_AV_STR_OPENED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_START_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* STR_CLOSE_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_CLEANUP, BTA_AV_INIT_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ,
- BTA_AV_CLOSING_SST},
+ /* AVDT_CONNECT_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
+ /* AVDT_DELAY_RPT_EVT */
+ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST}};
/* state table for opening state */
static const uint8_t bta_av_sst_opening[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* SDP_DISC_OK_EVT */ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* SDP_DISC_FAIL_EVT */ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_DISC_OK_EVT */ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_OPEN_OK_EVT */ {BTA_AV_ST_RC_TIMER, BTA_AV_STR_OPENED,
- BTA_AV_OPEN_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* CI_SETCONFIG_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* SDP_DISC_OK_EVT */
+ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* SDP_DISC_FAIL_EVT */
+ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_DISC_OK_EVT */
+ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_OPEN_OK_EVT */
+ {BTA_AV_ST_RC_TIMER, BTA_AV_STR_OPENED, BTA_AV_OPEN_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE,
- BTA_AV_INCOMING_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* AVRC_TIMER_EVT */ {BTA_AV_SWITCH_ROLE, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* AVDT_CONNECT_EVT */ {BTA_AV_DISCOVER_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_CONN_FAILED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* AVRC_TIMER_EVT */
+ {BTA_AV_SWITCH_ROLE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* AVDT_CONNECT_EVT */
+ {BTA_AV_DISCOVER_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_CONN_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_ROLE_RES, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
+ /* AVDT_DELAY_RPT_EVT */
+ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPENING_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_OPENING_SST}};
/* state table for open state */
static const uint8_t bta_av_sst_open[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* API_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_DO_START, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* AP_STOP_EVT */ {BTA_AV_STR_STOPPED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* API_RECONFIG_EVT */ {BTA_AV_RECONFIG, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* API_RC_OPEN_EVT */ {BTA_AV_SET_USE_RC, BTA_AV_OPEN_RC, BTA_AV_OPEN_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_DATA_PATH, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_DATA_PATH, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
@@ -312,40 +313,40 @@
/* STR_OPEN_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_START_OK_EVT */ {BTA_AV_START_OK, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_START_FAILED, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_START_FAILED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* STR_CLOSE_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_CLR_CONG, BTA_AV_DATA_PATH,
- BTA_AV_OPEN_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SUSPEND_CFM, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* AVRC_TIMER_EVT */ {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START,
- BTA_AV_OPEN_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_CLR_CONG, BTA_AV_DATA_PATH, BTA_AV_OPEN_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SUSPEND_CFM, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* AVRC_TIMER_EVT */
+ {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START, BTA_AV_OPEN_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_ROLE_RES, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_OPEN_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_OPEN_SST}};
/* state table for reconfig state */
static const uint8_t bta_av_sst_rcfg[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* API_CLOSE_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* API_RECONFIG_EVT */ {BTA_AV_RECONFIG, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
@@ -354,109 +355,109 @@
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* STR_DISC_OK_EVT */ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* STR_DISC_OK_EVT */
+ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_OPEN_OK_EVT */ {BTA_AV_RCFG_STR_OK, BTA_AV_SIGNORE, BTA_AV_OPEN_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_RCFG_FAILED, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_RCFG_FAILED, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_CLOSE_EVT */ {BTA_AV_RCFG_CONNECT, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SUSPEND_CFM, BTA_AV_SUSPEND_CONT,
- BTA_AV_RCFG_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_RCFG_CFM, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SUSPEND_CFM, BTA_AV_SUSPEND_CONT, BTA_AV_RCFG_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_RCFG_CFM, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_RCFG_OPEN, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_RCFG_DISCNTD, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_RCFG_DISCNTD, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_RCFG_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_RCFG_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_RCFG_SST}};
/* state table for closing state */
static const uint8_t bta_av_sst_closing[][BTA_AV_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
- /* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* AP_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* API_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_CLOSE_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* API_PROTECT_REQ_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* API_PROTECT_RSP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* API_PROTECT_REQ_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_PROTECT_RSP_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* SRC_DATA_READY_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* CI_SETCONFIG_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* CI_SETCONFIG_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* SDP_DISC_OK_EVT */ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
- /* SDP_DISC_FAIL_EVT */ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* SDP_DISC_FAIL_EVT */
+ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_GETCAP_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* STR_DISC_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_GETCAP_OK_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_GETCAP_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* STR_OPEN_OK_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* STR_OPEN_FAIL_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* STR_OPEN_FAIL_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_REJ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* STR_START_FAIL_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_CLOSE_EVT */
+ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_CONFIG_IND_EVT */
+ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_SECURITY_IND_EVT */
+ {BTA_AV_SECURITY_REJ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_SECURITY_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_WRITE_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_SUSPEND_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* STR_RECONFIG_CFM_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE,
- BTA_AV_INIT_SST},
+ /* AVDT_DISCONNECT_EVT */
+ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* AVDT_DELAY_RPT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
+ /* AVDT_DELAY_RPT_EVT */
+ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
- /* API_OFFLOAD_START_EVT */ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST},
- /* API_OFFLOAD_START_RSP_EVT */ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE,
- BTA_AV_CLOSING_SST}};
+ /* API_OFFLOAD_START_EVT */
+ {BTA_AV_OFFLOAD_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST},
+ /* API_OFFLOAD_START_RSP_EVT */
+ {BTA_AV_OFFLOAD_RSP, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST}};
/* type for state table */
typedef const uint8_t (*tBTA_AV_SST_TBL)[BTA_AV_NUM_COLS];
@@ -466,7 +467,6 @@
bta_av_sst_init, bta_av_sst_incoming, bta_av_sst_opening,
bta_av_sst_open, bta_av_sst_rcfg, bta_av_sst_closing};
-static const char* bta_av_sst_code(uint8_t state);
/*******************************************************************************
*
@@ -480,49 +480,32 @@
******************************************************************************/
void bta_av_ssm_execute(tBTA_AV_SCB* p_scb, uint16_t event,
tBTA_AV_DATA* p_data) {
- tBTA_AV_SST_TBL state_table;
- uint8_t action;
- int i, xx;
-
if (p_scb == NULL) {
/* this stream is not registered */
- APPL_TRACE_EVENT("AV channel not registered");
+ APPL_TRACE_EVENT("%s: AV channel not registered", __func__);
return;
}
- /* In case incoming connection is for VDP, we need to swap scb. */
- /* When ACP_CONNECT_EVT was received, we put first available scb to */
- /* to Incoming state. Later, when STR_CONFIG_IND_EVT is coming, we */
- /* know if it is A2DP or VDP. */
- if ((p_scb->state == BTA_AV_INIT_SST) &&
- (event == BTA_AV_STR_CONFIG_IND_EVT)) {
- for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
- if (bta_av_cb.p_scb[xx]) {
- if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST) {
- bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
- bta_av_cb.p_scb[xx]->coll_mask = 0;
- p_scb->state = BTA_AV_INCOMING_SST;
- break;
- }
- }
- }
- }
-
- APPL_TRACE_VERBOSE("%s: AV Sevent(0x%x)=0x%x(%s) state=%d(%s)", __func__,
- p_scb->hndl, event, bta_av_evt_code(event), p_scb->state,
- bta_av_sst_code(p_scb->state));
+ APPL_TRACE_VERBOSE(
+ "%s: peer %s AV event(0x%x)=0x%x(%s) state=%d(%s) p_scb=%p", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->hndl, event,
+ bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state),
+ p_scb);
/* look up the state table for the current state */
- state_table = bta_av_sst_tbl[p_scb->state];
-
- event -= BTA_AV_FIRST_SSM_EVT;
+ tBTA_AV_SST_TBL state_table = bta_av_sst_tbl[p_scb->state];
/* set next state */
+ event -= BTA_AV_FIRST_SSM_EVT;
p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
+ APPL_TRACE_VERBOSE("%s: peer %s AV next state=%d(%s) p_scb=%p", __func__,
+ p_scb->peer_addr.ToString().c_str(), p_scb->state,
+ bta_av_sst_code(p_scb->state), p_scb);
+
/* execute action functions */
- for (i = 0; i < BTA_AV_SACTIONS; i++) {
- action = state_table[event][i];
+ for (int i = 0; i < BTA_AV_SACTIONS; i++) {
+ uint8_t action = state_table[event][i];
if (action != BTA_AV_SIGNORE) {
(*p_scb->p_act_tbl[action])(p_scb, p_data);
} else
@@ -581,9 +564,19 @@
*
******************************************************************************/
void bta_av_set_scb_sst_init(tBTA_AV_SCB* p_scb) {
- if (p_scb) {
- p_scb->state = BTA_AV_INIT_SST;
+ if (p_scb == nullptr) {
+ return;
}
+
+ uint8_t next_state = BTA_AV_INIT_SST;
+
+ APPL_TRACE_VERBOSE(
+ "%s: peer %s AV (hndl=0x%x) state=%d(%s) next state=%d(%s) p_scb=%p",
+ __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->state,
+ bta_av_sst_code(p_scb->state), next_state, bta_av_sst_code(next_state),
+ p_scb);
+
+ p_scb->state = next_state;
}
/*******************************************************************************
@@ -634,7 +627,7 @@
* Returns char *
*
******************************************************************************/
-static const char* bta_av_sst_code(uint8_t state) {
+const char* bta_av_sst_code(uint8_t state) {
switch (state) {
case BTA_AV_INIT_SST:
return "INIT";
diff --git a/bta/include/bta_ar_api.h b/bta/include/bta_ar_api.h
index 18fe59e..b2a8753 100644
--- a/bta/include/bta_ar_api.h
+++ b/bta/include/bta_ar_api.h
@@ -60,7 +60,7 @@
* Returns void
*
******************************************************************************/
-extern void bta_ar_reg_avdt(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback,
+extern void bta_ar_reg_avdt(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback,
tBTA_SYS_ID sys_id);
/*******************************************************************************
@@ -86,7 +86,8 @@
* Returns void
*
******************************************************************************/
-extern void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr);
+extern void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, const RawAddress& bd_addr,
+ uint8_t scb_index);
/*******************************************************************************
*
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
index 83ec437..07105ef 100644
--- a/bta/include/bta_av_api.h
+++ b/bta/include/bta_av_api.h
@@ -91,9 +91,9 @@
/* handle index to mask */
#define BTA_AV_HNDL_TO_MSK(h) ((uint8_t)(1 << (h)))
-/* maximum number of streams created: 1 for audio, 1 for video */
+/* maximum number of streams created */
#ifndef BTA_AV_NUM_STRS
-#define BTA_AV_NUM_STRS 2
+#define BTA_AV_NUM_STRS 6
#endif
#ifndef BTA_AV_MAX_A2DP_MTU
@@ -101,10 +101,6 @@
#define BTA_AV_MAX_A2DP_MTU 1008
#endif
-#ifndef BTA_AV_MAX_VDP_MTU
-#define BTA_AV_MAX_VDP_MTU 1008
-#endif
-
/* operation id list for BTA_AvRemoteCmd */
typedef uint8_t tBTA_AV_RC;
@@ -199,7 +195,7 @@
bool suspending;
} tBTA_AV_START;
-/* data associated with BTA_AV_SUSPEND_EVT */
+/* data associated with BTA_AV_SUSPEND_EVT, BTA_AV_STOP_EVT */
typedef struct {
tBTA_AV_CHNL chnl;
tBTA_AV_HNDL hndl;
@@ -367,9 +363,6 @@
union tBTA_AV_DATA;
typedef void (*tBTA_AV_ACT)(tBTA_AV_SCB* p_cb, tBTA_AV_DATA* p_data);
-/* type for registering VDP */
-typedef void(tBTA_AV_REG)(tAVDT_CS* p_cs, char* p_service_name, void* p_data);
-
/* AV configuration structure */
typedef struct {
uint32_t company_id; /* AVRCP Company ID */
@@ -382,8 +375,6 @@
const uint16_t*
p_audio_flush_to; /* AVDTP audio transport channel flush timeout */
uint16_t audio_mqs; /* AVDTP audio channel max data queue size */
- uint16_t video_mtu; /* AVDTP video transport channel MTU at L2CAP */
- uint16_t video_flush_to; /* AVDTP video transport channel flush timeout */
bool avrc_group; /* true, to accept AVRC 1.3 group nevigation command */
uint8_t num_co_ids; /* company id count in p_meta_co_ids */
uint8_t num_evt_ids; /* event id count in p_meta_evt_ids */
@@ -393,8 +384,7 @@
p_meta_co_ids; /* the metadata Get Capabilities response for company id */
const uint8_t* p_meta_evt_ids; /* the the metadata Get Capabilities response
for event id */
- const tBTA_AV_ACT* p_act_tbl; /* the action function table for VDP stream */
- tBTA_AV_REG* p_reg; /* action function to register VDP */
+ const tBTA_AV_ACT* p_act_tbl; /* action function table for audio stream */
char avrc_controller_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP controller
name */
char avrc_target_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP target name*/
@@ -505,7 +495,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStart(void);
+void BTA_AvStart(tBTA_AV_HNDL handle);
/*******************************************************************************
*
@@ -518,7 +508,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStop(bool suspend);
+void BTA_AvStop(tBTA_AV_HNDL handle, bool suspend);
/*******************************************************************************
*
@@ -704,4 +694,12 @@
******************************************************************************/
void BTA_AvOffloadStartRsp(tBTA_AV_HNDL hndl, tBTA_AV_STATUS status);
+/**
+ * Dump debug-related information for the BTA AV module.
+ *
+ * @param fd the file descriptor to use for writing the ASCII formatted
+ * information
+ */
+void bta_debug_av_dump(int fd);
+
#endif /* BTA_AV_API_H */
diff --git a/bta/include/bta_av_ci.h b/bta/include/bta_av_ci.h
index 94b94f6..07b59e6 100644
--- a/bta/include/bta_av_ci.h
+++ b/bta/include/bta_av_ci.h
@@ -35,7 +35,7 @@
*
* Description This function sends an event to the AV indicating that
* the phone has audio stream data ready to send and AV
- * should call bta_av_co_audio_src_data_path().
+ * should call bta_av_co_audio_source_data_path().
*
* Returns void
*
@@ -55,7 +55,7 @@
* Returns void
*
******************************************************************************/
-extern void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, uint8_t err_code,
+extern void bta_av_ci_setconfig(tBTA_AV_HNDL bta_av_handle, uint8_t err_code,
uint8_t category, uint8_t num_seid,
uint8_t* p_seid, bool recfg_needed,
uint8_t avdt_handle);
diff --git a/bta/include/bta_av_co.h b/bta/include/bta_av_co.h
index d5c979c..39bb4ff 100644
--- a/bta/include/bta_av_co.h
+++ b/bta/include/bta_av_co.h
@@ -45,7 +45,7 @@
*
******************************************************************************/
bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
+ AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
@@ -59,9 +59,10 @@
* Returns void.
*
******************************************************************************/
-void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps,
- uint8_t num_snk, uint8_t num_src,
- const RawAddress& addr, uint16_t uuid_local);
+void bta_av_co_audio_disc_res(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint8_t num_seps,
+ uint8_t num_sinks, uint8_t num_sources,
+ uint16_t uuid_local);
/*******************************************************************************
*
@@ -75,7 +76,9 @@
* Returns Stream codec and content protection configuration info.
*
******************************************************************************/
-tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
+tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
uint8_t* p_sep_info_idx, uint8_t seid,
uint8_t* p_num_protect,
uint8_t* p_protect_info);
@@ -92,8 +95,9 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info,
- uint8_t seid, const RawAddress& addr,
+void bta_av_co_audio_setconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, uint8_t seid,
uint8_t num_protect,
const uint8_t* p_protect_info,
uint8_t t_local_sep, uint8_t avdt_handle);
@@ -111,7 +115,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu);
+void bta_av_co_audio_open(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu);
/*******************************************************************************
*
@@ -127,7 +132,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_close(tBTA_AV_HNDL hndl);
+void bta_av_co_audio_close(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
/*******************************************************************************
*
@@ -140,8 +146,9 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_start(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
- bool* p_no_rtp_hdr);
+void bta_av_co_audio_start(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header);
/*******************************************************************************
*
@@ -154,11 +161,12 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_stop(tBTA_AV_HNDL hndl);
+void bta_av_co_audio_stop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
/*******************************************************************************
*
- * Function bta_av_co_audio_src_data_path
+ * Function bta_av_co_audio_source_data_path
*
* Description This function is called to get the next data buffer from
* the audio codec
@@ -167,14 +175,14 @@
* Otherwise, a buffer (BT_HDR*) containing the audio data.
*
******************************************************************************/
-void* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info,
- uint32_t* p_timestamp);
+BT_HDR* bta_av_co_audio_source_data_path(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp);
/*******************************************************************************
*
* Function bta_av_co_audio_drop
*
- * Description An Audio packet is dropped. .
+ * Description An Audio packet is dropped.
* It's very likely that the connected headset with this handle
* is moved far away. The implementation may want to reduce
* the encoder bit rate setting to reduce the packet size.
@@ -182,7 +190,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_drop(tBTA_AV_HNDL hndl);
+void bta_av_co_audio_drop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
/*******************************************************************************
*
@@ -196,7 +205,8 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay);
+void bta_av_co_audio_delay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t delay);
/*******************************************************************************
*
@@ -211,6 +221,7 @@
* Returns void
*
******************************************************************************/
-void bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu);
+void bta_av_co_audio_update_mtu(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu);
#endif /* BTA_AV_CO_H */
diff --git a/bta/sys/bta_sys_conn.cc b/bta/sys/bta_sys_conn.cc
index 01cd055..3c3bc63 100644
--- a/bta/sys/bta_sys_conn.cc
+++ b/bta/sys/bta_sys_conn.cc
@@ -99,6 +99,8 @@
******************************************************************************/
void bta_sys_notify_role_chg(const RawAddress& p_bda, uint8_t new_role,
uint8_t hci_status) {
+ APPL_TRACE_DEBUG("%s: peer %s new_role:%d hci_status:0x%x", __func__,
+ p_bda.ToString().c_str(), new_role, hci_status);
if (bta_sys_cb.p_role_cb) {
bta_sys_cb.p_role_cb(BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda);
}
diff --git a/btif/Android.bp b/btif/Android.bp
index b6ab774..88b3cfa 100644
--- a/btif/Android.bp
+++ b/btif/Android.bp
@@ -65,7 +65,6 @@
"src/btif_rc.cc",
"src/btif_sdp.cc",
"src/btif_sdp_server.cc",
- "src/btif_sm.cc",
"src/btif_sock.cc",
"src/btif_sock_rfc.cc",
"src/btif_sock_l2cap.cc",
@@ -108,6 +107,7 @@
srcs: ["test/btif_storage_test.cc"],
header_libs: ["libbluetooth_headers"],
shared_libs: [
+ "libaudioclient",
"libhidlbase",
"liblog",
"libprotobuf-cpp-lite",
@@ -115,17 +115,20 @@
"libutils",
],
static_libs: [
- "libbtif",
"libbt-bta",
"libbtcore",
"libbt-stack",
+ "libbt-sbc-encoder",
+ "libFraunhoferAAC",
"libbtdevice",
"libbt-hci",
+ "libudrv-uipc",
"libbluetooth-types",
"libosi",
"libbt-protos",
],
whole_static_libs: [
+ "libbtif",
"libbluetooth-for-tests",
],
cflags: ["-DBUILDCFG"],
@@ -152,3 +155,25 @@
],
cflags: ["-DBUILDCFG"],
}
+
+// btif state machine unit tests for target
+// ========================================================
+cc_test {
+ name: "net_test_btif_state_machine",
+ defaults: ["fluoride_defaults"],
+ include_dirs: btifCommonIncludes,
+ host_supported: true,
+ srcs: [
+ "test/btif_state_machine_test.cc"
+ ],
+ header_libs: ["libbluetooth_headers"],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ ],
+ static_libs: [
+ "libbluetooth-types",
+ "libosi",
+ ],
+ cflags: ["-DBUILDCFG"],
+}
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
index 598a512..f0c80a7 100644
--- a/btif/BUILD.gn
+++ b/btif/BUILD.gn
@@ -50,7 +50,6 @@
"src/btif_rc.cc",
"src/btif_sdp.cc",
"src/btif_sdp_server.cc",
- "src/btif_sm.cc",
"src/btif_sock.cc",
"src/btif_sock_l2cap.cc",
"src/btif_sock_rfc.cc",
diff --git a/btif/co/bta_av_co.cc b/btif/co/bta_av_co.cc
index ce76c19..c149ced 100644
--- a/btif/co/bta_av_co.cc
+++ b/btif/co/bta_av_co.cc
@@ -23,407 +23,808 @@
*
******************************************************************************/
-#include "bta_av_co.h"
+#include <mutex>
+
+#include <base/bind.h>
#include <base/logging.h>
#include <string.h>
+
+#include "bt_target.h"
+
#include "a2dp_api.h"
#include "a2dp_sbc.h"
-#include "bt_target.h"
#include "bta_av_api.h"
#include "bta_av_ci.h"
+#include "bta_av_co.h"
#include "bta_sys.h"
#include "btif_av.h"
#include "btif_av_co.h"
#include "btif_util.h"
-#include "osi/include/mutex.h"
#include "osi/include/osi.h"
-/*****************************************************************************
- ** Constants
- *****************************************************************************/
-
-/* Macro to retrieve the number of elements in a statically allocated array */
+// Macro to retrieve the number of elements in a statically allocated array
#define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a) / sizeof((__a)[0]))
-/* Macro to convert audio handle to index and vice versa */
-#define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
-#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
+// Macro to convert BTA AV audio handle to index and vice versa
+#define BTA_AV_CO_AUDIO_HANDLE_TO_INDEX(bta_av_handle) \
+ (((bta_av_handle) & (~BTA_AV_CHNL_MSK)) - 1)
+#define BTA_AV_CO_AUDIO_INDEX_TO_HANDLE(index) \
+ (((index) + 1) | BTA_AV_CHNL_AUDIO)
-/* SCMS-T protect info */
-const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00};
-
-/*****************************************************************************
- * Local data
- ****************************************************************************/
-typedef struct {
- uint8_t sep_info_idx; /* local SEP index (in BTA tables) */
- uint8_t seid; /* peer SEP index (in peer tables) */
- uint8_t codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */
- uint8_t num_protect; /* peer SEP number of CP elements */
- uint8_t protect_info[AVDT_CP_INFO_LEN]; /* peer SEP content protection info */
-} tBTA_AV_CO_SINK;
-
-typedef struct {
- RawAddress addr; /* address of audio/video peer */
- tBTA_AV_CO_SINK
- sinks[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported sinks */
- tBTA_AV_CO_SINK srcs[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported srcs */
- uint8_t num_sinks; /* total number of sinks at peer */
- uint8_t num_srcs; /* total number of srcs at peer */
- uint8_t num_seps; /* total number of seids at peer */
- uint8_t num_rx_sinks; /* number of received sinks */
- uint8_t num_rx_srcs; /* number of received srcs */
- uint8_t num_sup_sinks; /* number of supported sinks in the sinks array */
- uint8_t num_sup_srcs; /* number of supported srcs in the srcs array */
- const tBTA_AV_CO_SINK* p_sink; /* currently selected sink */
- const tBTA_AV_CO_SINK* p_src; /* currently selected src */
- uint8_t codec_config[AVDT_CODEC_SIZE]; /* current codec configuration */
- bool cp_active; /* current CP configuration */
- bool acp; /* acceptor */
- bool reconfig_needed; /* reconfiguration is needed */
- bool opened; /* opened */
- uint16_t mtu; /* maximum transmit unit size */
- uint16_t uuid_to_connect; /* uuid of peer device */
- tBTA_AV_HNDL handle; /* handle to use */
-} tBTA_AV_CO_PEER;
-
-typedef struct {
- bool active;
- uint8_t flag;
-} tBTA_AV_CO_CP;
-
-class BtaAvCoCb {
+class BtaAvCoSep {
public:
- BtaAvCoCb() : codecs(nullptr) { reset(); }
-
- /* Connected peer information */
- tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
- /* Current codec configuration - access to this variable must be protected */
- uint8_t codec_config[AVDT_CODEC_SIZE];
- A2dpCodecs* codecs; /* Locally supported codecs */
- tBTA_AV_CO_CP cp;
-
- void reset() {
- delete codecs;
- codecs = nullptr;
- // TODO: Ugly leftover reset from the original C code. Should go away once
- // the rest of the code in this file migrates to C++.
- memset(peers, 0, sizeof(peers));
- memset(codec_config, 0, sizeof(codec_config));
- memset(&cp, 0, sizeof(cp));
-
- // Initialize the handles
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers); i++) {
- tBTA_AV_CO_PEER* p_peer = &peers[i];
- p_peer->handle = BTA_AV_CO_AUDIO_INDX_TO_HNDL(i);
- }
+ BtaAvCoSep()
+ : sep_info_idx(0), seid(0), codec_caps{}, num_protect(0), protect_info{} {
+ Reset();
}
+
+ /**
+ * Reset the state.
+ */
+ void Reset() {
+ sep_info_idx = 0;
+ seid = 0;
+ memset(codec_caps, 0, sizeof(codec_caps));
+ num_protect = 0;
+ memset(protect_info, 0, sizeof(protect_info));
+ }
+
+ uint8_t sep_info_idx; // Local SEP index (in BTA tables)
+ uint8_t seid; // Peer SEP index (in peer tables)
+ uint8_t codec_caps[AVDT_CODEC_SIZE]; // Peer SEP codec capabilities
+ uint8_t num_protect; // Peer SEP number of CP elements
+ uint8_t protect_info[AVDT_CP_INFO_LEN]; // Peer SEP content protection info
};
-/* Control block instance */
-static BtaAvCoCb bta_av_co_cb;
-
-static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info);
-static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect,
- const uint8_t* p_protect_info);
-static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
- const tBTA_AV_CO_PEER* p_peer);
-static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer);
-static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
- A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer);
-static bool bta_av_co_audio_update_selectable_codec(
- A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer);
-static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* new_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info);
-static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* p_ota_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info,
- bool* p_restart_output);
-
-/*******************************************************************************
- **
- ** Function bta_av_co_cp_get_flag
- **
- ** Description Get content protection flag
- ** AVDT_CP_SCMS_COPY_NEVER
- ** AVDT_CP_SCMS_COPY_ONCE
- ** AVDT_CP_SCMS_COPY_FREE
- **
- ** Returns The current flag value
- **
- ******************************************************************************/
-static uint8_t bta_av_co_cp_get_flag(void) { return bta_av_co_cb.cp.flag; }
-
-/*******************************************************************************
- **
- ** Function bta_av_co_cp_set_flag
- **
- ** Description Set content protection flag
- ** AVDT_CP_SCMS_COPY_NEVER
- ** AVDT_CP_SCMS_COPY_ONCE
- ** AVDT_CP_SCMS_COPY_FREE
- **
- ** Returns true if setting the SCMS flag is supported else false
- **
- ******************************************************************************/
-static bool bta_av_co_cp_set_flag(uint8_t cp_flag) {
- APPL_TRACE_DEBUG("%s: cp_flag = %d", __func__, cp_flag);
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
-#else
- if (cp_flag != AVDT_CP_SCMS_COPY_FREE) {
- return false;
+class BtaAvCoPeer {
+ public:
+ BtaAvCoPeer()
+ : addr(RawAddress::kEmpty),
+ num_sinks(0),
+ num_sources(0),
+ num_seps(0),
+ num_rx_sinks(0),
+ num_rx_sources(0),
+ num_sup_sinks(0),
+ num_sup_sources(0),
+ p_sink(nullptr),
+ p_source(nullptr),
+ codec_config{},
+ acceptor(false),
+ reconfig_needed(false),
+ opened(false),
+ mtu(0),
+ uuid_to_connect(0),
+ bta_av_handle_(0),
+ codecs_(nullptr),
+ content_protect_active_(false) {
+ Reset(0);
}
+
+ /**
+ * Initialize the state.
+ *
+ * @param codec_priorities the codec priorities to use for the initialization
+ */
+ void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
+
+ /**
+ * Reset the state.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ */
+ void Reset(tBTA_AV_HNDL bta_av_handle);
+
+ /**
+ * Get the BTA AV handle.
+ *
+ * @return the BTA AV handle
+ */
+ tBTA_AV_HNDL BtaAvHandle() const { return bta_av_handle_; }
+
+ /**
+ * Get the A2DP codecs.
+ *
+ * @return the A2DP codecs
+ */
+ A2dpCodecs* GetCodecs() { return codecs_; }
+
+ bool ContentProtectActive() const { return content_protect_active_; }
+ void SetContentProtectActive(bool cp_active) {
+ content_protect_active_ = cp_active;
+ }
+
+ RawAddress addr; // Peer address
+ BtaAvCoSep sinks[BTAV_A2DP_CODEC_INDEX_MAX]; // Supported sinks
+ BtaAvCoSep sources[BTAV_A2DP_CODEC_INDEX_MAX]; // Supported sources
+ uint8_t num_sinks; // Total number of sinks at peer
+ uint8_t num_sources; // Total number of sources at peer
+ uint8_t num_seps; // Total number of SEPs at peer
+ uint8_t num_rx_sinks; // Number of received sinks
+ uint8_t num_rx_sources; // Number of received sources
+ uint8_t num_sup_sinks; // Number of supported sinks
+ uint8_t num_sup_sources; // Number of supported sources
+ const BtaAvCoSep* p_sink; // Currently selected sink
+ const BtaAvCoSep* p_source; // Currently selected source
+ uint8_t codec_config[AVDT_CODEC_SIZE]; // Current codec configuration
+ bool acceptor; // True if acceptor
+ bool reconfig_needed; // True if reconfiguration is needed
+ bool opened; // True if opened
+ uint16_t mtu; // Maximum Transmit Unit size
+ uint16_t uuid_to_connect; // UUID of peer device
+
+ private:
+ tBTA_AV_HNDL bta_av_handle_; // BTA AV handle to use
+ A2dpCodecs* codecs_; // Locally supported codecs
+ bool content_protect_active_; // True if Content Protect is active
+};
+
+class BtaAvCo {
+ public:
+ BtaAvCo(bool content_protect_enabled)
+ : active_peer_(nullptr),
+ codec_config_{},
+ content_protect_enabled_(content_protect_enabled),
+ content_protect_flag_(0) {
+ Reset();
+ }
+
+ /**
+ * Initialize the state.
+ *
+ * @param codec_priorities the codec priorities to use for the initialization
+ */
+ void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
+
+ /**
+ * Get the current codec configuration for the active peer.
+ *
+ * @return the current codec configuration if found, otherwise nullptr
+ */
+ A2dpCodecConfig* GetActivePeerCurrentCodec();
+
+ /**
+ * Find the peer UUID for a given BTA AV handle.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ * @return the peer UUID if found, otherwise 0
+ */
+ uint16_t FindPeerUuid(tBTA_AV_HNDL bta_av_handle);
+
+ /**
+ * Process the AVDTP discovery result: number of Stream End Points (SEP)
+ * found during the AVDTP stream discovery process.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param num_seps the number of discovered SEPs
+ * @param num_sinks number of discovered Sink SEPs
+ * @param num_sources number of discovered Source SEPs
+ * @param uuid_local local UUID
+ */
+ void ProcessDiscoveryResult(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint8_t num_seps,
+ uint8_t num_sinks, uint8_t num_sources,
+ uint16_t uuid_local);
+
+ /**
+ * Process retrieved codec configuration and content protection from
+ * Peer Source SEP.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the peer sink capability filled-in by the caller.
+ * On success, it will contain the current codec configuration for the peer.
+ * @param p_sep_info_idx the peer SEP index for the corresponding peer
+ * sink capability filled-in by the caller. On success, it will contain
+ * the SEP index for the current codec configuration for the peer.
+ * @param seid the peer SEP index in peer tables
+ * @param p_num_protect the peer SEP number of content protection elements
+ * filled-in by the caller. On success, it will contain the SEP number of
+ * content protection elements for the current codec configuration for the
+ * peer.
+ * @param p_protect_info the peer SEP content protection info filled-in by
+ * the caller. On success, it will contain the SEP content protection info
+ * for the current codec configuration for the peer.
+ * @return A2DP_SUCCESS on success, otherwise A2DP_FAIL
+ */
+ tA2DP_STATUS ProcessSourceGetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect,
+ uint8_t* p_protect_info);
+
+ /**
+ * Process retrieved codec configuration and content protection from
+ * Peer Source SEP.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the peer source capability filled-in by the caller.
+ * On success, it will contain the current codec configuration for the peer.
+ * @param p_sep_info_idx the peer SEP index for the corresponding peer
+ * source capability filled-in by the caller. On success, it will contain
+ * the SEP index for the current codec configuration for the peer.
+ * @param seid the peer SEP index in peer tables
+ * @param p_num_protect the peer SEP number of content protection elements
+ * filled-in by the caller. On success, it will contain the SEP number of
+ * content protection elements for the current codec configuration for the
+ * peer.
+ * @param p_protect_info the peer SEP content protection info filled-in by
+ * the caller. On success, it will contain the SEP content protection info
+ * for the current codec configuration for the peer.
+ * @return A2DP_SUCCESS on success, otherwise A2DP_FAIL
+ */
+ tA2DP_STATUS ProcessSinkGetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect,
+ uint8_t* p_protect_info);
+
+ /**
+ * Process AVDTP Set Config to set the codec and content protection
+ * configuration of the audio stream.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the codec configuration to set
+ * @param seid stream endpoint ID of stream initiating the operation
+ * @param peer_address the peer address
+ * @param num_protect the peer SEP number of content protection elements
+ * @param p_protect_info the peer SEP conntent protection info
+ * @param t_local_sep the local SEP: AVDT_TSEP_SRC or AVDT_TSEP_SNK
+ * @param avdt_handle the AVDTP handle
+ */
+ void ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, uint8_t seid,
+ uint8_t num_protect, const uint8_t* p_protect_info,
+ uint8_t t_local_sep, uint8_t avdt_handle);
+
+ /**
+ * Process AVDTP Open when the stream connection is opened.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param mtu the MTU of the connection
+ */
+ void ProcessOpen(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ uint16_t mtu);
+
+ /**
+ * Process AVDTP Close when the stream connection is closed.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ */
+ void ProcessClose(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
+
+ /**
+ * Process AVDTP Start when the audio data streaming is started.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param p_codec_info the codec configuration
+ * @param p_no_rtp_header on return, set to true if the audio data packets
+ * should not contain RTP header
+ */
+ void ProcessStart(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header);
+
+ /**
+ * Process AVDTP Stop when the audio data streaming is stopped.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ */
+ void ProcessStop(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
+
+ /**
+ * Get the next encoded audio data packet to send.
+ *
+ * @param p_codec_info the codec configuration
+ * @param p_timestamp on return, set to the timestamp of the data packet
+ * @return the next encoded data packet or nullptr if no encoded data to send
+ */
+ BT_HDR* GetNextSourceDataPacket(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp);
+
+ /**
+ * An audio packet has been dropped.
+ * This signal can be used by the encoder to reduce the encoder bit rate
+ * setting.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ */
+ void DataPacketWasDropped(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
+
+ /**
+ * Process AVDTP Audio Delay when the initial delay report is received by
+ * the Source.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param delay the reported delay in 1/10th of a millisecond
+ */
+ void ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t delay);
+
+ /**
+ * Update the MTU of the audio data connection.
+ *
+ * @param bta_av_handle the BTA AV handle to identify the peer
+ * @param peer_address the peer address
+ * @param mtu the new MTU of the audio data connection
+ */
+ void UpdateMtu(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ uint16_t mtu);
+
+ /**
+ * Set the active peer.
+ *
+ * @param peer_address the peer address
+ * @return true on success, otherwise false
+ */
+ bool SetActivePeer(const RawAddress& peer_address);
+
+ /**
+ * Get the encoder parameters for a peer.
+ *
+ * @param peer_address the peer address
+ * @param p_peer_params on return, set to the peer's encoder parameters
+ */
+ void GetPeerEncoderParameters(const RawAddress& peer_address,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
+
+ /**
+ * Get the Source encoder interface for the current codec.
+ *
+ * @return the Source encoder interface for the current codec
+ */
+ const tA2DP_ENCODER_INTERFACE* GetSourceEncoderInterface();
+
+ /**
+ * Get the Sink decoder interface for the current codec.
+ *
+ * @return the Sink decoder interface for the current codec
+ */
+ const tA2DP_DECODER_INTERFACE* GetSinkDecoderInterface();
+
+ /**
+ * Set the codec user configuration.
+ *
+ * @param peer_address the peer address
+ * @param codec_user_config the codec user configuration to set
+ * @return true on success, otherwise false
+ */
+ bool SetCodecUserConfig(const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config);
+
+ /**
+ * Set the codec audio configuration.
+ *
+ * @param codec_audio_config the codec audio configuration to set
+ * @return true on success, otherwise false
+ */
+ bool SetCodecAudioConfig(const btav_a2dp_codec_config_t& codec_audio_config);
+
+ /**
+ * Report the source codec state for a peer
+ *
+ * @param p_peer the peer to report
+ * @return true on success, otherwise false
+ */
+ bool ReportSourceCodecState(BtaAvCoPeer* p_peer);
+
+ /**
+ * Get the content protection flag.
+ *
+ * @return the content protection flag. It should be one of the following:
+ * AVDT_CP_SCMS_COPY_NEVER, AVDT_CP_SCMS_COPY_ONCE, AVDT_CP_SCMS_COPY_FREE
+ */
+ uint8_t ContentProtectFlag() const { return content_protect_flag_; }
+
+ /**
+ * Set the content protection flag.
+ *
+ * @param cp_flag the content protection flag. It should be one of the
+ * following:
+ * AVDT_CP_SCMS_COPY_NEVER, AVDT_CP_SCMS_COPY_ONCE, AVDT_CP_SCMS_COPY_FREE
+ * NOTE: If Content Protection is not enabled on the system, then
+ * the only acceptable vailue is AVDT_CP_SCMS_COPY_FREE.
+ */
+ void SetContentProtectFlag(uint8_t cp_flag) {
+ if (!ContentProtectEnabled() && (cp_flag != AVDT_CP_SCMS_COPY_FREE)) {
+ return;
+ }
+ content_protect_flag_ = cp_flag;
+ }
+
+ /**
+ * Dump debug-related information.
+ *
+ * @param fd the file descritor to use for writing the ASCII formatted
+ * information
+ */
+ void DebugDump(int fd);
+
+ private:
+ /**
+ * Reset the state.
+ */
+ void Reset();
+
+ /**
+ * Find the peer entry for a given peer address.
+ *
+ * @param peer_address the peer address to use
+ * @return the peer entry if found, otherwise nullptr
+ */
+ BtaAvCoPeer* FindPeer(const RawAddress& peer_address);
+
+ /**
+ * Find the peer entry for a given BTA AV handle.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ * @return the peer entry if found, otherwise nullptr
+ */
+ BtaAvCoPeer* FindPeer(tBTA_AV_HNDL bta_av_handle);
+
+ /**
+ * Find the peer entry for a given BTA AV handle and update it with the
+ * peer address.
+ *
+ * @param bta_av_handle the BTA AV handle to use
+ * @param peer_address the peer address
+ * @return the peer entry if found, otherwise nullptr
+ */
+ BtaAvCoPeer* FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address);
+
+ /**
+ * Find the Source Peer SEP that supports the current codec config.
+ *
+ * @param p_peer the peer to use
+ * @return the peer SEP that supports the current codec config, otherwise
+ * nullptr
+ */
+ const BtaAvCoSep* FindPeerSourceSepForCurrentCodec(const BtaAvCoPeer* p_peer);
+
+ /**
+ * Select the Source codec configuration based on peer codec support.
+ *
+ * Furthermore, the local state for the remaining non-selected codecs is
+ * updated to reflect whether the codec is selectable.
+ *
+ * @param p_peer the peer to use
+ * @return a pointer to the corresponding SEP Sink entry on success,
+ * otherwise nullptr
+ */
+ BtaAvCoSep* SelectSourceCodec(BtaAvCoPeer* p_peer);
+
+ /**
+ * Save new codec configuration.
+ *
+ * @param p_peer the peer to use
+ * @param new_codec_config the new codec configuration to use
+ * @param num_protect the number of content protection elements
+ * @param p_protect_info the content protection info to use
+ */
+ void SaveNewCodecConfig(BtaAvCoPeer* p_peer, const uint8_t* new_codec_config,
+ uint8_t num_protect, const uint8_t* p_protect_info);
+
+ /**
+ * Set the Over-The-Air preferred codec configuration.
+ *
+ * The OTA prefered codec configuration is ignored if the current
+ * codec configuration contains explicit user configuration, or if the
+ * codec configuration for the same codec contains explicit user
+ * configuration.
+ *
+ * @param p_peer is the peer device that sent the OTA codec configuration
+ * @param p_ota_codec_config contains the received OTA A2DP codec
+ * configuration from the remote peer. Note: this is not the peer codec
+ * capability, but the codec configuration that the peer would like to use.
+ * @param num_protect is the number of content protection methods to use
+ * @param p_protect_info contains the content protection information to use.
+ * @param p_restart_output if there is a change in the encoder configuration
+ * that requires restarting of the A2DP connection, flag |p_restart_output|
+ * is set to true.
+ * @return true on success, otherwise false
+ */
+ bool SetCodecOtaConfig(BtaAvCoPeer* p_peer, const uint8_t* p_ota_codec_config,
+ uint8_t num_protect, const uint8_t* p_protect_info,
+ bool* p_restart_output);
+
+ /**
+ * Update a selectable codec with the corresponding codec information from
+ * a peer device.
+ *
+ * @param codec_config the codec config info to identify the codec to update
+ * @param p_peer the peer to use
+ * @return true if the codec is updated, otherwise false
+ */
+ bool UpdateSelectableCodec(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer);
+
+ /**
+ * Attempt to select codec configuration for a peer.
+ *
+ * @param codec_config the codec configuration to use
+ * @param p_peer the peer to use
+ * @return a pointer to the corresponding SEP Sink entry on success,
+ * otnerwise nullptr
+ */
+ BtaAvCoSep* AttemptCodecSelection(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer);
+
+ /**
+ * Check if a Sink SEP has content protection enabled.
+ *
+ * @param p_sink the peer Sink SEP to check
+ * @return true if the peer Sink SEP has content protection enabled,
+ * otherwise false
+ */
+ bool AudioSinkHasContentProtection(const BtaAvCoSep* p_sink);
+
+ /**
+ * Check if a content protection service is SCMS-T.
+ *
+ * @param p_orotect_info the content protection info to check
+ * @return true if the Contention Protection in @param p_protect_info
+ * is SCMS-T, otherwise false
+ */
+ static bool ContentProtectIsScmst(const uint8_t* p_protect_info);
+
+ /**
+ * Check if audio protect info contains SCMS-T Content Protection.
+ *
+ * @param num_protect number of protect schemes
+ * @param p_protect_info the protect info to check
+ * @return true if @param p_protect_info contains SCMS-T, otherwise false
+ */
+ static bool AudioProtectHasScmst(uint8_t num_protect,
+ const uint8_t* p_protect_info);
+
+ bool ContentProtectEnabled() const { return content_protect_enabled_; }
+
+ std::recursive_mutex codec_lock_; // Protect access to the codec state
+ std::vector<btav_a2dp_codec_config_t> codec_priorities_; // Configured
+ BtaAvCoPeer peers_[BTA_AV_NUM_STRS]; // Connected peer information
+ BtaAvCoPeer* active_peer_; // The current active peer
+ uint8_t codec_config_[AVDT_CODEC_SIZE]; // Current codec configuration
+ const bool content_protect_enabled_; // True if Content Protect is enabled
+ uint8_t content_protect_flag_; // Content Protect flag
+};
+
+// SCMS-T protect info
+const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00};
+
+// Control block instance
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+static const bool kContentProtectEnabled = true;
+#else
+static const bool kContentProtectEnabled = false;
#endif
- bta_av_co_cb.cp.flag = cp_flag;
- return true;
+static BtaAvCo bta_av_co_cb(kContentProtectEnabled);
+
+void BtaAvCoPeer::Init(
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
+ Reset(bta_av_handle_);
+
+ // Reset the current config
+ codecs_ = new A2dpCodecs(codec_priorities);
+ codecs_->init();
+ A2DP_InitDefaultCodec(codec_config);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_get_peer
- **
- ** Description find the peer entry for a given handle
- **
- ** Returns the control block
- **
- ******************************************************************************/
-static tBTA_AV_CO_PEER* bta_av_co_get_peer(tBTA_AV_HNDL hndl) {
+void BtaAvCoPeer::Reset(tBTA_AV_HNDL bta_av_handle) {
+ addr = RawAddress::kEmpty;
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(sinks); i++) {
+ BtaAvCoSep& sink = sinks[i];
+ sink.Reset();
+ }
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(sources); i++) {
+ BtaAvCoSep& source = sources[i];
+ source.Reset();
+ }
+ num_sinks = 0;
+ num_sources = 0;
+ num_seps = 0;
+ num_rx_sinks = 0;
+ num_rx_sources = 0;
+ num_sup_sinks = 0;
+ num_sup_sources = 0;
+ p_sink = nullptr;
+ p_source = nullptr;
+ memset(codec_config, 0, sizeof(codec_config));
+ acceptor = false;
+ reconfig_needed = false;
+ opened = false;
+ mtu = 0;
+ uuid_to_connect = 0;
+
+ bta_av_handle_ = bta_av_handle;
+ delete codecs_;
+ codecs_ = nullptr;
+ content_protect_active_ = false;
+}
+
+void BtaAvCo::Init(
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ // Reset the control block
+ Reset();
+ codec_priorities_ = codec_priorities;
+
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ BtaAvCoPeer* p_peer = &peers_[i];
+ p_peer->Init(codec_priorities);
+ }
+}
+
+void BtaAvCo::Reset() {
+ codec_priorities_.clear();
+ active_peer_ = nullptr;
+ content_protect_flag_ = 0;
+ memset(codec_config_, 0, sizeof(codec_config_));
+
+ if (ContentProtectEnabled()) {
+ SetContentProtectFlag(AVDT_CP_SCMS_COPY_NEVER);
+ } else {
+ SetContentProtectFlag(AVDT_CP_SCMS_COPY_FREE);
+ }
+
+ // Reset the peers and initialize the handles
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ BtaAvCoPeer* p_peer = &peers_[i];
+ p_peer->Reset(BTA_AV_CO_AUDIO_INDEX_TO_HANDLE(i));
+ }
+}
+
+A2dpCodecConfig* BtaAvCo::GetActivePeerCurrentCodec() {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ if (active_peer_ == nullptr || active_peer_->GetCodecs() == nullptr) {
+ return nullptr;
+ }
+ return active_peer_->GetCodecs()->getCurrentCodecConfig();
+}
+
+BtaAvCoPeer* BtaAvCo::FindPeer(const RawAddress& peer_address) {
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ BtaAvCoPeer* p_peer = &peers_[i];
+ if (p_peer->addr == peer_address) {
+ return p_peer;
+ }
+ }
+ return nullptr;
+}
+
+BtaAvCoPeer* BtaAvCo::FindPeer(tBTA_AV_HNDL bta_av_handle) {
uint8_t index;
- index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
+ index = BTA_AV_CO_AUDIO_HANDLE_TO_INDEX(bta_av_handle);
- APPL_TRACE_DEBUG("%s: handle = %d index = %d", __func__, hndl, index);
+ APPL_TRACE_DEBUG("%s: bta_av_handle = 0x%x index = %d", __func__,
+ bta_av_handle, index);
- /* Sanity check */
- if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) {
- APPL_TRACE_ERROR("%s: peer index out of bounds: %d", __func__, index);
- return NULL;
+ // Sanity check
+ if (index >= BTA_AV_CO_NUM_ELEMENTS(peers_)) {
+ APPL_TRACE_ERROR(
+ "%s: peer index %d for BTA AV handle 0x%x is out of bounds", __func__,
+ index, bta_av_handle);
+ return nullptr;
}
- return &bta_av_co_cb.peers[index];
+ return &peers_[index];
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_init
- **
- ** Description This callout function is executed by AV when it is
- ** started by calling BTA_AvRegister(). This function can be
- ** used by the phone to initialize audio paths or for other
- ** initialization purposes.
- **
- **
- ** Returns Stream codec and content protection capabilities info.
- **
- ******************************************************************************/
-bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg) {
- return A2DP_InitCodecConfig(codec_index, p_cfg);
+BtaAvCoPeer* BtaAvCo::FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle = 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+
+ BtaAvCoPeer* p_peer = FindPeer(bta_av_handle);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR("%s: peer for BTA AV handle 0x%x not found", __func__,
+ bta_av_handle);
+ return nullptr;
+ }
+
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle = 0x%x previous address %s",
+ __func__, peer_address.ToString().c_str(), bta_av_handle,
+ p_peer->addr.ToString().c_str());
+ p_peer->addr = peer_address;
+ return p_peer;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_disc_res
- **
- ** Description This callout function is executed by AV to report the
- ** number of stream end points (SEP) were found during the
- ** AVDT stream discovery process.
- **
- **
- ** Returns void.
- **
- ******************************************************************************/
-void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps,
- uint8_t num_sink, uint8_t num_src,
- const RawAddress& addr, uint16_t uuid_local) {
- tBTA_AV_CO_PEER* p_peer;
+uint16_t BtaAvCo::FindPeerUuid(tBTA_AV_HNDL bta_av_handle) {
+ BtaAvCoPeer* p_peer = FindPeer(bta_av_handle);
+ if (p_peer == nullptr) {
+ return 0;
+ }
+ return p_peer->uuid_to_connect;
+}
- APPL_TRACE_DEBUG("%s: h:x%x num_seps:%d num_sink:%d num_src:%d", __func__,
- hndl, num_seps, num_sink, num_src);
+void BtaAvCo::ProcessDiscoveryResult(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t num_seps, uint8_t num_sinks,
+ uint8_t num_sources, uint16_t uuid_local) {
+ APPL_TRACE_DEBUG(
+ "%s: peer %s bta_av_handle:0x%x num_seps:%d num_sinks:%d num_sources:%d",
+ __func__, peer_address.ToString().c_str(), bta_av_handle, num_seps,
+ num_sinks, num_sources);
- /* Find the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
return;
}
/* Sanity check : this should never happen */
if (p_peer->opened) {
- APPL_TRACE_ERROR("%s: peer already opened", __func__);
+ APPL_TRACE_ERROR("%s: peer %s already opened", __func__,
+ peer_address.ToString().c_str());
}
/* Copy the discovery results */
- p_peer->addr = addr;
- p_peer->num_sinks = num_sink;
- p_peer->num_srcs = num_src;
+ p_peer->addr = peer_address;
+ p_peer->num_sinks = num_sinks;
+ p_peer->num_sources = num_sources;
p_peer->num_seps = num_seps;
p_peer->num_rx_sinks = 0;
- p_peer->num_rx_srcs = 0;
+ p_peer->num_rx_sources = 0;
p_peer->num_sup_sinks = 0;
- if (uuid_local == UUID_SERVCLASS_AUDIO_SINK)
+ if (uuid_local == UUID_SERVCLASS_AUDIO_SINK) {
p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
- else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE)
+ } else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE) {
p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
+ }
}
-/*******************************************************************************
- **
- ** Function bta_av_audio_sink_getconfig
- **
- ** Description This callout function is executed by AV to retrieve the
- ** desired codec and content protection configuration for the
- ** A2DP Sink audio stream in Initiator.
- **
- **
- ** Returns Pass or Fail for current getconfig.
- **
- ******************************************************************************/
-static tA2DP_STATUS bta_av_audio_sink_getconfig(
- tBTA_AV_HNDL hndl, uint8_t* p_codec_info, uint8_t* p_sep_info_idx,
- uint8_t seid, uint8_t* p_num_protect, uint8_t* p_protect_info) {
- tA2DP_STATUS result = A2DP_FAIL;
- tBTA_AV_CO_PEER* p_peer;
-
- APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl,
+tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig(
+ tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
+ uint8_t* p_codec_info, uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect, uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle:0x%x codec:%s seid:%d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle,
A2DP_CodecName(p_codec_info), seid);
APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
__func__, *p_num_protect, p_protect_info[0],
p_protect_info[1], p_protect_info[2]);
-
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
- return A2DP_FAIL;
- }
-
- APPL_TRACE_DEBUG("%s: peer(o=%d,n_sinks=%d,n_rx_sinks=%d,n_sup_sinks=%d)",
- __func__, p_peer->opened, p_peer->num_srcs,
- p_peer->num_rx_srcs, p_peer->num_sup_srcs);
-
- p_peer->num_rx_srcs++;
-
- /* Check the peer's SOURCE codec */
- if (A2DP_IsPeerSourceCodecValid(p_codec_info)) {
- /* If there is room for a new one */
- if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)) {
- tBTA_AV_CO_SINK* p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
-
- APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
- p_codec_info[1], p_codec_info[2], p_codec_info[3],
- p_codec_info[4], p_codec_info[5], p_codec_info[6]);
-
- memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
- p_src->sep_info_idx = *p_sep_info_idx;
- p_src->seid = seid;
- p_src->num_protect = *p_num_protect;
- memcpy(p_src->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
- } else {
- APPL_TRACE_ERROR("%s: no more room for SRC info", __func__);
- }
- }
-
- /* If last SINK get capabilities or all supported codec caps retrieved */
- if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
- (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))) {
- APPL_TRACE_DEBUG("%s: last SRC reached", __func__);
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
-
- /* Find a src that matches the codec config */
- const tBTA_AV_CO_SINK* p_src =
- bta_av_co_find_peer_src_supports_codec(p_peer);
- if (p_src != NULL) {
- uint8_t pref_config[AVDT_CODEC_SIZE];
- APPL_TRACE_DEBUG("%s: codec supported", __func__);
-
- /* Build the codec configuration for this sink */
- /* Save the new configuration */
- p_peer->p_src = p_src;
- /* get preferred config from src_caps */
- if (A2DP_BuildSrc2SinkConfig(p_src->codec_caps, pref_config) !=
- A2DP_SUCCESS) {
- mutex_global_unlock();
- return A2DP_FAIL;
- }
- memcpy(p_peer->codec_config, pref_config, AVDT_CODEC_SIZE);
-
- APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
- p_peer->codec_config[1], p_peer->codec_config[2],
- p_peer->codec_config[3], p_peer->codec_config[4],
- p_peer->codec_config[5], p_peer->codec_config[6]);
- /* By default, no content protection */
- *p_num_protect = 0;
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- p_peer->cp_active = false;
- bta_av_co_cb.cp.active = false;
-#endif
-
- *p_sep_info_idx = p_src->sep_info_idx;
- memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
- result = A2DP_SUCCESS;
- }
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
- }
- return result;
-}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_getconfig
- **
- ** Description This callout function is executed by AV to retrieve the
- ** desired codec and content protection configuration for the
- ** audio stream.
- **
- **
- ** Returns Stream codec and content protection configuration info.
- **
- ******************************************************************************/
-tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
- uint8_t* p_sep_info_idx, uint8_t seid,
- uint8_t* p_num_protect,
- uint8_t* p_protect_info) {
- tBTA_AV_CO_PEER* p_peer;
-
- APPL_TRACE_DEBUG("%s", __func__);
A2DP_DumpCodecInfo(p_codec_info);
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
return A2DP_FAIL;
}
-
- if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) {
- return bta_av_audio_sink_getconfig(hndl, p_codec_info, p_sep_info_idx, seid,
- p_num_protect, p_protect_info);
- }
- APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl,
- A2DP_CodecName(p_codec_info), seid);
- APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
- __func__, *p_num_protect, p_protect_info[0],
- p_protect_info[1], p_protect_info[2]);
APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
__func__, p_peer->opened, p_peer->num_sinks,
p_peer->num_rx_sinks, p_peer->num_sup_sinks);
p_peer->num_rx_sinks++;
- /* Check the peer's SINK codec */
+ // Check the peer's Sink codec
if (A2DP_IsPeerSinkCodecValid(p_codec_info)) {
- /* If there is room for a new one */
+ // If there is room for a new one
if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) {
- tBTA_AV_CO_SINK* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
+ BtaAvCoSep* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
p_codec_info[1], p_codec_info[2], p_codec_info[3],
@@ -435,42 +836,42 @@
p_sink->num_protect = *p_num_protect;
memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
} else {
- APPL_TRACE_ERROR("%s: no more room for SINK info", __func__);
+ APPL_TRACE_ERROR("%s: no more room for Sink info", __func__);
}
}
- // Check if this is the last SINK get capabilities or all supported codec
+ // Check if this is the last Sink get capabilities or all supported codec
// capabilities are retrieved.
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
return A2DP_FAIL;
}
- APPL_TRACE_DEBUG("%s: last sink reached", __func__);
+ APPL_TRACE_DEBUG("%s: last Sink reached", __func__);
- const tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_set_codec(p_peer);
- if (p_sink == NULL) {
- APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__);
+ // Select the Source codec
+ const BtaAvCoSep* p_sink = SelectSourceCodec(p_peer);
+ if (p_sink == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot set up codec for the peer Sink", __func__);
return A2DP_FAIL;
}
// By default, no content protection
*p_num_protect = 0;
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (p_peer->cp_active) {
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
*p_num_protect = AVDT_CP_INFO_LEN;
memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN);
}
-#endif
- // If acceptor -> reconfig otherwise reply for configuration.
- if (p_peer->acp) {
- // Stop fetching caps once we retrieved a supported codec.
+ // If acceptor -> reconfig otherwise reply for configuration
+ if (p_peer->acceptor) {
+ // Stop fetching caps once we retrieved a supported codec
APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__);
*p_sep_info_idx = p_peer->num_seps;
if (p_peer->reconfig_needed) {
- APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, hndl);
- BTA_AvReconfig(hndl, true, p_sink->sep_info_idx, p_peer->codec_config,
- *p_num_protect, bta_av_co_cp_scmst);
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
+ bta_av_handle);
+ BTA_AvReconfig(bta_av_handle, true, p_sink->sep_info_idx,
+ p_peer->codec_config, *p_num_protect, bta_av_co_cp_scmst);
}
} else {
*p_sep_info_idx = p_sink->sep_info_idx;
@@ -480,103 +881,201 @@
return A2DP_SUCCESS;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_setconfig
- **
- ** Description This callout function is executed by AV to set the codec
- ** and content protection configuration of the audio stream.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info,
- UNUSED_ATTR uint8_t seid,
- UNUSED_ATTR const RawAddress& addr,
- uint8_t num_protect,
+tA2DP_STATUS BtaAvCo::ProcessSinkGetConfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx,
+ uint8_t seid, uint8_t* p_num_protect,
+ uint8_t* p_protect_info) {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle:0x%x codec:%s seid:%d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle,
+ A2DP_CodecName(p_codec_info), seid);
+ APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
+ __func__, *p_num_protect, p_protect_info[0],
+ p_protect_info[1], p_protect_info[2]);
+ A2DP_DumpCodecInfo(p_codec_info);
+
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return A2DP_FAIL;
+ }
+ APPL_TRACE_DEBUG(
+ "%s: peer %s found (o=%d, n_sources=%d, n_rx_sources=%d, "
+ "n_sup_sources=%d)",
+ __func__, p_peer->addr.ToString().c_str(), p_peer->opened,
+ p_peer->num_sources, p_peer->num_rx_sources, p_peer->num_sup_sources);
+
+ p_peer->num_rx_sources++;
+
+ // Check the peer's Source codec
+ if (A2DP_IsPeerSourceCodecValid(p_codec_info)) {
+ // If there is room for a new one
+ if (p_peer->num_sup_sources < BTA_AV_CO_NUM_ELEMENTS(p_peer->sources)) {
+ BtaAvCoSep* p_source = &p_peer->sources[p_peer->num_sup_sources++];
+
+ APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
+ p_codec_info[1], p_codec_info[2], p_codec_info[3],
+ p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+
+ memcpy(p_source->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
+ p_source->sep_info_idx = *p_sep_info_idx;
+ p_source->seid = seid;
+ p_source->num_protect = *p_num_protect;
+ memcpy(p_source->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
+ } else {
+ APPL_TRACE_ERROR("%s: no more room for Source info", __func__);
+ }
+ }
+
+ // Check if this is the last Source get capabilities or all supported codec
+ // capabilities are retrieved.
+ if ((p_peer->num_rx_sources != p_peer->num_sources) &&
+ (p_peer->num_sup_sources != BTA_AV_CO_NUM_ELEMENTS(p_peer->sources))) {
+ return A2DP_FAIL;
+ }
+ APPL_TRACE_DEBUG("%s: last Source reached", __func__);
+
+ // Find a Peer SEP that matches the codec config
+ const BtaAvCoSep* p_source = FindPeerSourceSepForCurrentCodec(p_peer);
+ if (p_source == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot set up codec for the peer Source", __func__);
+ return A2DP_FAIL;
+ }
+
+ uint8_t pref_config[AVDT_CODEC_SIZE];
+ APPL_TRACE_DEBUG("%s: codec supported", __func__);
+
+ // Build the codec configuration for this Sink and save the new config
+ p_peer->p_source = p_source;
+ // Get preferred config from Source capabilities
+ if (A2DP_BuildSrc2SinkConfig(p_source->codec_caps, pref_config) !=
+ A2DP_SUCCESS) {
+ return A2DP_FAIL;
+ }
+ memcpy(p_peer->codec_config, pref_config, AVDT_CODEC_SIZE);
+
+ APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
+ p_peer->codec_config[1], p_peer->codec_config[2],
+ p_peer->codec_config[3], p_peer->codec_config[4],
+ p_peer->codec_config[5], p_peer->codec_config[6]);
+ // By default, no content protection
+ *p_num_protect = 0;
+
+ if (ContentProtectEnabled()) {
+ p_peer->SetContentProtectActive(false);
+ }
+
+ *p_sep_info_idx = p_source->sep_info_idx;
+ memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
+
+ return A2DP_SUCCESS;
+}
+
+void BtaAvCo::ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
+ UNUSED_ATTR const RawAddress& peer_address,
+ const uint8_t* p_codec_info,
+ UNUSED_ATTR uint8_t seid, uint8_t num_protect,
const uint8_t* p_protect_info,
uint8_t t_local_sep, uint8_t avdt_handle) {
- tBTA_AV_CO_PEER* p_peer;
tA2DP_STATUS status = A2DP_SUCCESS;
uint8_t category = A2DP_SUCCESS;
bool reconfig_needed = false;
+ APPL_TRACE_DEBUG(
+ "%s: bta_av_handle=0x%x peer_address=%s seid=%d "
+ "num_protect=%d t_local_sep=%d avdt_handle=%d",
+ __func__, bta_av_handle, peer_address.ToString().c_str(), seid,
+ num_protect, t_local_sep, avdt_handle);
APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
p_codec_info[1], p_codec_info[2], p_codec_info[3],
p_codec_info[4], p_codec_info[5], p_codec_info[6]);
- APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
- num_protect, p_protect_info[0], p_protect_info[1],
+ APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
+ __func__, num_protect, p_protect_info[0], p_protect_info[1],
p_protect_info[2]);
A2DP_DumpCodecInfo(p_codec_info);
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
- /* Call call-in rejecting the configuration */
- bta_av_ci_setconfig(hndl, A2DP_BUSY, AVDT_ASC_CODEC, 0, NULL, false,
- avdt_handle);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ // Call call-in rejecting the configuration
+ bta_av_ci_setconfig(bta_av_handle, A2DP_BUSY, AVDT_ASC_CODEC, 0, nullptr,
+ false, avdt_handle);
return;
}
- APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
- __func__, p_peer->opened, p_peer->num_sinks,
- p_peer->num_rx_sinks, p_peer->num_sup_sinks);
+ APPL_TRACE_DEBUG(
+ "%s: peer %s found (o=%d, n_sinks=%d, n_rx_sinks=%d, "
+ "n_sup_sinks=%d)",
+ __func__, p_peer->addr.ToString().c_str(), p_peer->opened,
+ p_peer->num_sinks, p_peer->num_rx_sinks, p_peer->num_sup_sinks);
- /* Sanity check: should not be opened at this point */
+ // Sanity check: should not be opened at this point
if (p_peer->opened) {
- APPL_TRACE_ERROR("%s: peer already in use", __func__);
+ APPL_TRACE_ERROR("%s: peer %s already in use", __func__,
+ p_peer->addr.ToString().c_str());
}
if (num_protect != 0) {
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- /* If CP is supported */
- if ((num_protect != 1) || (!bta_av_co_cp_is_scmst(p_protect_info))) {
- APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
+ if (ContentProtectEnabled()) {
+ if ((num_protect != 1) ||
+ !BtaAvCo::ContentProtectIsScmst(p_protect_info)) {
+ APPL_TRACE_ERROR("%s: wrong CP configuration for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
+ status = A2DP_BAD_CP_TYPE;
+ category = AVDT_ASC_PROTECT;
+ }
+ } else {
+ // Do not support content protection for the time being
+ APPL_TRACE_ERROR("%s: wrong CP configuration for peer %s", __func__,
+ p_peer->addr.ToString().c_str());
status = A2DP_BAD_CP_TYPE;
category = AVDT_ASC_PROTECT;
}
-#else
- /* Do not support content protection for the time being */
- APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
- status = A2DP_BAD_CP_TYPE;
- category = AVDT_ASC_PROTECT;
-#endif
}
if (status == A2DP_SUCCESS) {
bool codec_config_supported = false;
if (t_local_sep == AVDT_TSEP_SNK) {
- APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__);
+ APPL_TRACE_DEBUG("%s: peer %s is A2DP Source", __func__,
+ p_peer->addr.ToString().c_str());
codec_config_supported = A2DP_IsSinkCodecSupported(p_codec_info);
if (codec_config_supported) {
- // If Peer is SRC, and our config subset matches with what is
+ // If Peer is Source, and our config subset matches with what is
// requested by peer, then just accept what peer wants.
- bta_av_co_save_new_codec_config(p_peer, p_codec_info, num_protect,
- p_protect_info);
+ SaveNewCodecConfig(p_peer, p_codec_info, num_protect, p_protect_info);
}
}
if (t_local_sep == AVDT_TSEP_SRC) {
- APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__);
+ APPL_TRACE_DEBUG("%s: peer %s is A2DP SINK", __func__,
+ p_peer->addr.ToString().c_str());
bool restart_output = false;
- if ((bta_av_co_cb.codecs == nullptr) ||
- !bta_av_co_set_codec_ota_config(p_peer, p_codec_info, num_protect,
- p_protect_info, &restart_output)) {
- APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
- A2DP_CodecName(p_codec_info));
+ if ((p_peer->GetCodecs() == nullptr) ||
+ !SetCodecOtaConfig(p_peer, p_codec_info, num_protect, p_protect_info,
+ &restart_output)) {
+ APPL_TRACE_ERROR("%s: cannot set source codec %s for peer %s", __func__,
+ A2DP_CodecName(p_codec_info),
+ p_peer->addr.ToString().c_str());
} else {
codec_config_supported = true;
// Check if reconfiguration is needed
if (restart_output ||
- ((num_protect == 1) && (!bta_av_co_cb.cp.active))) {
+ ((num_protect == 1) && !p_peer->ContentProtectActive())) {
reconfig_needed = true;
}
}
}
- /* Check if codec configuration is supported */
+ // Check if codec configuration is supported
if (!codec_config_supported) {
category = AVDT_ASC_CODEC;
status = A2DP_WRONG_CODEC;
@@ -584,124 +1083,105 @@
}
if (status != A2DP_SUCCESS) {
- APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category);
- /* Call call-in rejecting the configuration */
- bta_av_ci_setconfig(hndl, status, category, 0, NULL, false, avdt_handle);
+ APPL_TRACE_DEBUG("%s: peer %s reject s=%d c=%d", __func__,
+ p_peer->addr.ToString().c_str(), status, category);
+ // Call call-in rejecting the configuration
+ bta_av_ci_setconfig(bta_av_handle, status, category, 0, nullptr, false,
+ avdt_handle);
return;
}
- /* Mark that this is an acceptor peer */
- p_peer->acp = true;
+ // Mark that this is an acceptor peer
+ p_peer->acceptor = true;
p_peer->reconfig_needed = reconfig_needed;
- APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, reconfig_needed);
- /* Call call-in accepting the configuration */
- bta_av_ci_setconfig(hndl, A2DP_SUCCESS, A2DP_SUCCESS, 0, NULL,
+ APPL_TRACE_DEBUG("%s: peer %s accept reconf=%d", __func__,
+ p_peer->addr.ToString().c_str(), reconfig_needed);
+ // Call call-in accepting the configuration
+ bta_av_ci_setconfig(bta_av_handle, A2DP_SUCCESS, A2DP_SUCCESS, 0, nullptr,
reconfig_needed, avdt_handle);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_open
- **
- ** Description This function is called by AV when the audio stream
- ** connection is opened.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu) {
- tBTA_AV_CO_PEER* p_peer;
+void BtaAvCo::ProcessOpen(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x mtu:%d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, mtu);
- APPL_TRACE_DEBUG("%s: handle: %d mtu:%d", __func__, hndl, mtu);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return;
+ }
+ p_peer->opened = true;
+ p_peer->mtu = mtu;
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
- } else {
- p_peer->opened = true;
- p_peer->mtu = mtu;
+ // The first connected peer becomes the active peer
+ if (active_peer_ == nullptr) {
+ active_peer_ = p_peer;
}
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_close
- **
- ** Description This function is called by AV when the audio stream
- ** connection is closed.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_close(tBTA_AV_HNDL hndl) {
- tBTA_AV_CO_PEER* p_peer;
+void BtaAvCo::ProcessClose(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer) {
- /* Mark the peer closed and clean the peer info */
- memset(p_peer, 0, sizeof(*p_peer));
- } else {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return;
}
+ // Reset the active peer
+ if (active_peer_ == p_peer) {
+ active_peer_ = nullptr;
+ }
+ // Mark the peer closed and clean the peer info
+ p_peer->Init(codec_priorities_);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_start
- **
- ** Description This function is called by AV when the audio streaming data
- ** transfer is started.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_start(UNUSED_ATTR tBTA_AV_HNDL hndl,
- UNUSED_ATTR uint8_t* p_codec_info,
- UNUSED_ATTR bool* p_no_rtp_hdr) {
- APPL_TRACE_DEBUG("%s", __func__);
+void BtaAvCo::ProcessStart(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
+ return;
+ }
+
+ bool add_rtp_header =
+ A2DP_UsesRtpHeader(p_peer->ContentProtectActive(), p_codec_info);
+
+ APPL_TRACE_DEBUG("%s: bta_av_handle: 0x%x add_rtp_header: %s", __func__,
+ bta_av_handle, add_rtp_header ? "true" : "false");
+ *p_no_rtp_header = !add_rtp_header;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_stop
- **
- ** Description This function is called by AV when the audio streaming data
- ** transfer is stopped.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_stop(UNUSED_ATTR tBTA_AV_HNDL hndl) {
- APPL_TRACE_DEBUG("%s", __func__);
+void BtaAvCo::ProcessStop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
+ // Nothing to do
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_src_data_path
- **
- ** Description This function is called to manage data transfer from
- ** the audio codec to AVDTP.
- **
- ** Returns Pointer to the GKI buffer to send, NULL if no buffer to
- ** send
- **
- ******************************************************************************/
-void* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info,
- uint32_t* p_timestamp) {
+BT_HDR* BtaAvCo::GetNextSourceDataPacket(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp) {
BT_HDR* p_buf;
APPL_TRACE_DEBUG("%s: codec: %s", __func__, A2DP_CodecName(p_codec_info));
p_buf = btif_a2dp_source_audio_readbuf();
- if (p_buf == NULL) return NULL;
+ if (p_buf == nullptr) return nullptr;
/*
* Retrieve the timestamp information from the media packet,
@@ -718,373 +1198,126 @@
A2DP_GetCodecType(p_codec_info));
}
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (bta_av_co_cb.cp.active) {
+ if (ContentProtectEnabled() && (active_peer_ != nullptr) &&
+ active_peer_->ContentProtectActive()) {
p_buf->len++;
p_buf->offset--;
uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- *p = bta_av_co_cp_get_flag();
+ *p = ContentProtectFlag();
}
-#endif
return p_buf;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_drop
- **
- ** Description An Audio packet is dropped. .
- ** It's very likely that the connected headset with this
- ** handle is moved far away. The implementation may want to
- ** reduce the encoder bit rate setting to reduce the packet
- ** size.
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_drop(tBTA_AV_HNDL hndl) {
- APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x", __func__, hndl);
+void BtaAvCo::DataPacketWasDropped(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ APPL_TRACE_ERROR("%s: peer %s dropped audio packet on handle 0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle);
}
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_delay
- **
- ** Description This function is called by AV when the audio stream
- ** connection needs to send the initial delay report to the
- ** connected SRC.
- **
- **
- ** Returns void
- **
- ******************************************************************************/
-void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) {
- APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay);
+void BtaAvCo::ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint16_t delay) {
+ APPL_TRACE_ERROR("%s: peer %s bta_av_handle: 0x%x delay:0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, delay);
+ // Nothing to do
}
-void bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu) {
- tBTA_AV_CO_PEER* p_peer;
+void BtaAvCo::UpdateMtu(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x mtu: %d", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, mtu);
- APPL_TRACE_DEBUG("%s: handle: %d mtu: %d", __func__, hndl, mtu);
-
- /* Retrieve the peer info */
- p_peer = bta_av_co_get_peer(hndl);
- if (p_peer == NULL) {
- APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR(
+ "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
+ __func__, bta_av_handle, peer_address.ToString().c_str());
return;
}
p_peer->mtu = mtu;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_cp_is_scmst
- **
- ** Description Check if a content protection service is SCMS-T
- **
- ** Returns true if this CP is SCMS-T, false otherwise
- **
- ******************************************************************************/
-static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info) {
- APPL_TRACE_DEBUG("%s", __func__);
+bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
- if (*p_protect_info >= AVDT_CP_LOSC) {
- uint16_t cp_id;
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- p_protect_info++;
- STREAM_TO_UINT16(cp_id, p_protect_info);
- if (cp_id == AVDT_CP_SCMS_T_ID) {
- APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
- return true;
- }
+ if (peer_address.IsEmpty()) {
+ // Reset the active peer;
+ active_peer_ = nullptr;
+ memset(codec_config_, 0, sizeof(codec_config_));
+ return true;
}
- return false;
-}
-
-// Check if audio protect info contains SCMS-T Copy Protection
-// Returns true if |p_protect_info| contains SCMS-T, otherwise false.
-static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect,
- const uint8_t* p_protect_info) {
- APPL_TRACE_DEBUG("%s", __func__);
-
- while (num_protect--) {
- if (bta_av_co_cp_is_scmst(p_protect_info)) return true;
- /* Move to the next SC */
- p_protect_info += *p_protect_info + 1;
- }
- APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__);
- return false;
-}
-
-/*******************************************************************************
- **
- ** Function bta_av_co_audio_sink_supports_cp
- **
- ** Description Check if a sink supports the current content protection
- **
- ** Returns true if the sink supports this CP, false otherwise
- **
- ******************************************************************************/
-static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK* p_sink) {
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* Check if content protection is enabled for this stream */
- if (bta_av_co_cp_get_flag() != AVDT_CP_SCMS_COPY_FREE) {
- return bta_av_co_audio_protect_has_scmst(p_sink->num_protect,
- p_sink->protect_info);
+ // Find the peer
+ BtaAvCoPeer* p_peer = FindPeer(peer_address);
+ if (p_peer == nullptr) {
+ return false;
}
- APPL_TRACE_DEBUG("%s: not required", __func__);
+ active_peer_ = p_peer;
+ memcpy(codec_config_, active_peer_->codec_config, AVDT_CODEC_SIZE);
+ ReportSourceCodecState(active_peer_);
return true;
}
-/*******************************************************************************
- **
- ** Function bta_av_co_find_peer_src_supports_codec
- **
- ** Description Find a peer acting as src that supports codec config
- **
- ** Returns The peer source that supports the codec, otherwise NULL.
- **
- ******************************************************************************/
-static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
- const tBTA_AV_CO_PEER* p_peer) {
- APPL_TRACE_DEBUG("%s: peer num_sup_srcs = %d", __func__,
- p_peer->num_sup_srcs);
-
- for (size_t index = 0; index < p_peer->num_sup_srcs; index++) {
- const uint8_t* p_codec_caps = p_peer->srcs[index].codec_caps;
- if (A2DP_CodecTypeEquals(bta_av_co_cb.codec_config, p_codec_caps) &&
- A2DP_IsPeerSourceCodecSupported(p_codec_caps)) {
- return &p_peer->srcs[index];
- }
- }
- return NULL;
-}
-
-//
-// Select the current codec configuration based on peer codec support.
-// Furthermore, the local state for the remaining non-selected codecs is
-// updated to reflect whether the codec is selectable.
-// Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry
-// on success, otherwise NULL.
-//
-static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) {
- tBTA_AV_CO_SINK* p_sink = NULL;
-
- // Update all selectable codecs.
- // This is needed to update the selectable parameters for each codec.
- // NOTE: The selectable codec info is used only for informational purpose.
- for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
- APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
- iter->name().c_str());
- bta_av_co_audio_update_selectable_codec(*iter, p_peer);
- }
-
- // Select the codec
- for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
- APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
- p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
- if (p_sink != NULL) {
- APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
- break;
- }
- APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
- }
-
- // NOTE: Unconditionally dispatch the event to make sure a callback with
- // the most recent codec info is generated.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, &p_peer->addr,
- sizeof(RawAddress));
-
- return p_sink;
-}
-
-// Select an open device for the preferred codec specified by |codec_config|.
-// Return the corresponding peer that supports the codec, otherwise NULL.
-static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
- A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer) {
- uint8_t new_codec_config[AVDT_CODEC_SIZE];
-
- APPL_TRACE_DEBUG("%s", __func__);
-
- // Find the peer sink for the codec
- tBTA_AV_CO_SINK* p_sink = NULL;
- for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
- btav_a2dp_codec_index_t peer_codec_index =
- A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
- if (peer_codec_index != codec_config.codecIndex()) {
- continue;
- }
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
- APPL_TRACE_DEBUG(
- "%s: peer sink for codec %s does not support "
- "Copy Protection",
- __func__, codec_config.name().c_str());
- continue;
- }
- p_sink = &p_peer->sinks[index];
- break;
- }
- if (p_sink == NULL) {
- APPL_TRACE_DEBUG("%s: peer sink for codec %s not found", __func__,
- codec_config.name().c_str());
- return NULL;
- }
- if (!bta_av_co_cb.codecs->setCodecConfig(
- p_sink->codec_caps, true /* is_capability */, new_codec_config,
- true /* select_current_codec */)) {
- APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
- codec_config.name().c_str());
- return NULL;
- }
- p_peer->p_sink = p_sink;
-
- bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect,
- p_sink->protect_info);
- // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller
-
- return p_sink;
-}
-
-// Update a selectable codec |codec_config| with the corresponding codec
-// information from a peer device |p_peer|.
-// Returns true if the codec is updated, otherwise false.
-static bool bta_av_co_audio_update_selectable_codec(
- A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) {
- uint8_t new_codec_config[AVDT_CODEC_SIZE];
-
- APPL_TRACE_DEBUG("%s", __func__);
-
- // Find the peer sink for the codec
- const tBTA_AV_CO_SINK* p_sink = NULL;
- for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
- btav_a2dp_codec_index_t peer_codec_index =
- A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
- if (peer_codec_index != codec_config.codecIndex()) {
- continue;
- }
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
- APPL_TRACE_DEBUG(
- "%s: peer sink for codec %s does not support "
- "Copy Protection",
- __func__, codec_config.name().c_str());
- continue;
- }
- p_sink = &p_peer->sinks[index];
- break;
- }
- if (p_sink == NULL) {
- // The peer sink device does not support this codec
- return false;
- }
- if (!bta_av_co_cb.codecs->setCodecConfig(
- p_sink->codec_caps, true /* is_capability */, new_codec_config,
- false /* select_current_codec */)) {
- APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__,
- codec_config.name().c_str());
- return false;
- }
- return true;
-}
-
-static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* new_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info) {
- APPL_TRACE_DEBUG("%s", __func__);
- A2DP_DumpCodecInfo(new_codec_config);
-
- // Protect access to bta_av_co_cb.codec_config
- mutex_global_lock();
-
- memcpy(bta_av_co_cb.codec_config, new_codec_config,
- sizeof(bta_av_co_cb.codec_config));
- memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE);
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- /* Check if this sink supports SCMS */
- bool cp_active =
- bta_av_co_audio_protect_has_scmst(num_protect, p_protect_info);
- bta_av_co_cb.cp.active = cp_active;
- p_peer->cp_active = cp_active;
-#endif
-
- // Protect access to bta_av_co_cb.codec_config
- mutex_global_unlock();
-}
-
-void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
+void BtaAvCo::GetPeerEncoderParameters(
+ const RawAddress& peer_address,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
uint16_t min_mtu = 0xFFFF;
- APPL_TRACE_DEBUG("%s", __func__);
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
CHECK(p_peer_params != nullptr);
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- /* Compute the MTU */
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
- const tBTA_AV_CO_PEER* p_peer = &bta_av_co_cb.peers[i];
+ // Compute the MTU
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ const BtaAvCoPeer* p_peer = &peers_[i];
if (!p_peer->opened) continue;
+ if (p_peer->addr != peer_address) continue;
if (p_peer->mtu < min_mtu) min_mtu = p_peer->mtu;
}
p_peer_params->peer_mtu = min_mtu;
- p_peer_params->is_peer_edr = btif_av_is_peer_edr();
- p_peer_params->peer_supports_3mbps = btif_av_peer_supports_3mbps();
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
+ p_peer_params->is_peer_edr = btif_av_is_peer_edr(peer_address);
+ p_peer_params->peer_supports_3mbps =
+ btif_av_peer_supports_3mbps(peer_address);
}
-const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
+const tA2DP_ENCODER_INTERFACE* BtaAvCo::GetSourceEncoderInterface() {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- const tA2DP_ENCODER_INTERFACE* encoder_interface =
- A2DP_GetEncoderInterface(bta_av_co_cb.codec_config);
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
-
- return encoder_interface;
+ return A2DP_GetEncoderInterface(codec_config_);
}
-const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void) {
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
+const tA2DP_DECODER_INTERFACE* BtaAvCo::GetSinkDecoderInterface() {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- const tA2DP_DECODER_INTERFACE* decoder_interface =
- A2DP_GetDecoderInterface(bta_av_co_cb.codec_config);
-
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_unlock();
-
- return decoder_interface;
+ return A2DP_GetDecoderInterface(codec_config_);
}
-bool bta_av_co_set_codec_user_config(
+bool BtaAvCo::SetCodecUserConfig(
+ const RawAddress& peer_address,
const btav_a2dp_codec_config_t& codec_user_config) {
uint8_t result_codec_config[AVDT_CODEC_SIZE];
- const tBTA_AV_CO_SINK* p_sink = nullptr;
+ const BtaAvCoSep* p_sink = nullptr;
bool restart_input = false;
bool restart_output = false;
bool config_updated = false;
bool success = true;
- // Find the peer that is currently open
- tBTA_AV_CO_PEER* p_peer = nullptr;
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
- tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i];
- if (p_peer_tmp->opened) {
- p_peer = p_peer_tmp;
- break;
- }
- }
+ APPL_TRACE_DEBUG("%s: peer_address=%s codec_user_config=%s", __func__,
+ peer_address.ToString().c_str(),
+ codec_user_config.ToString().c_str());
+
+ BtaAvCoPeer* p_peer = FindPeer(peer_address);
if (p_peer == nullptr) {
- APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
+ APPL_TRACE_ERROR("%s: cannot find peer %s to configure", __func__,
+ peer_address.ToString().c_str());
success = false;
goto done;
}
@@ -1095,7 +1328,9 @@
btav_a2dp_codec_index_t peer_codec_index =
A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
if (peer_codec_index != codec_user_config.codec_type) continue;
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue;
+ if (!AudioSinkHasContentProtection(&p_peer->sinks[index])) {
+ continue;
+ }
p_sink = &p_peer->sinks[index];
break;
}
@@ -1111,8 +1346,8 @@
}
tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
- bta_av_co_get_peer_params(&peer_params);
- if (!bta_av_co_cb.codecs->setCodecUserConfig(
+ GetPeerEncoderParameters(p_peer->addr, &peer_params);
+ if (!p_peer->GetCodecs()->setCodecUserConfig(
codec_user_config, &peer_params, p_sink->codec_caps,
result_codec_config, &restart_input, &restart_output,
&config_updated)) {
@@ -1122,12 +1357,12 @@
if (restart_output) {
uint8_t num_protect = 0;
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
-#endif
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
+ num_protect = AVDT_CP_INFO_LEN;
+ }
- p_sink = bta_av_co_audio_set_codec(p_peer);
- if (p_sink == NULL) {
+ p_sink = SelectSourceCodec(p_peer);
+ if (p_sink == nullptr) {
APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__);
success = false;
goto done;
@@ -1141,8 +1376,9 @@
goto done;
}
- APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, p_peer->handle);
- BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx,
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
+ p_peer->BtaAvHandle());
+ BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
}
@@ -1152,44 +1388,334 @@
// request succeeded or failed.
// NOTE: Currently, the input is restarted by sending an upcall
// and informing the Media Framework about the change.
- RawAddress empty_raw_address = RawAddress::kEmpty;
- RawAddress* p_addr;
if (p_peer != nullptr) {
- p_addr = &p_peer->addr;
- } else {
- p_addr = &empty_raw_address;
+ return ReportSourceCodecState(p_peer);
}
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, p_addr,
- sizeof(RawAddress));
return success;
}
-// Sets the Over-The-Air preferred codec configuration.
-// The OTA prefered codec configuration is ignored if the current
-// codec configuration contains explicit user configuration, or if the
-// codec configuration for the same codec contains explicit user
-// configuration.
-// |p_peer| is the peer device that sent the OTA codec configuration.
-// |p_ota_codec_config| contains the received OTA A2DP codec configuration
-// from the remote peer. Note: this is not the peer codec capability,
-// but the codec configuration that the peer would like to use.
-// |num_protect| is the number of content protection methods to use.
-// |p_protect_info| contains the content protection information to use.
-// If there is a change in the encoder configuration tht requires restarting
-// of the A2DP connection, flag |p_restart_output| is set to true.
-// Returns true on success, otherwise false.
-static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer,
- const uint8_t* p_ota_codec_config,
- uint8_t num_protect,
- const uint8_t* p_protect_info,
- bool* p_restart_output) {
+bool BtaAvCo::SetCodecAudioConfig(
+ const btav_a2dp_codec_config_t& codec_audio_config) {
+ uint8_t result_codec_config[AVDT_CODEC_SIZE];
+ bool restart_output = false;
+ bool config_updated = false;
+
+ APPL_TRACE_DEBUG("%s: codec_audio_config: %s", __func__,
+ codec_audio_config.ToString().c_str());
+
+ // Find the peer that is currently open
+ BtaAvCoPeer* p_peer = active_peer_;
+ if (p_peer == nullptr) {
+ APPL_TRACE_ERROR("%s: no active peer to configure", __func__);
+ return false;
+ }
+
+ // Use the current sink codec
+ const BtaAvCoSep* p_sink = p_peer->p_sink;
+ if (p_sink == nullptr) {
+ APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
+ return false;
+ }
+
+ tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
+ GetPeerEncoderParameters(p_peer->addr, &peer_params);
+ if (!p_peer->GetCodecs()->setCodecAudioConfig(
+ codec_audio_config, &peer_params, p_sink->codec_caps,
+ result_codec_config, &restart_output, &config_updated)) {
+ return false;
+ }
+
+ if (restart_output) {
+ uint8_t num_protect = 0;
+ if (ContentProtectEnabled() && p_peer->ContentProtectActive()) {
+ num_protect = AVDT_CP_INFO_LEN;
+ }
+
+ SaveNewCodecConfig(p_peer, result_codec_config, p_sink->num_protect,
+ p_sink->protect_info);
+
+ // Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
+ if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
+ (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
+ APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved",
+ __func__);
+ } else {
+ APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
+ p_peer->BtaAvHandle());
+ BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
+ p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
+ }
+ }
+
+ if (config_updated) {
+ // NOTE: Currently, the input is restarted by sending an upcall
+ // and informing the Media Framework about the change.
+ return ReportSourceCodecState(p_peer);
+ }
+
+ return true;
+}
+
+bool BtaAvCo::ReportSourceCodecState(BtaAvCoPeer* p_peer) {
+ btav_a2dp_codec_config_t codec_config;
+ std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
+ std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
+
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ p_peer->addr.ToString().c_str());
+ if (!p_peer->GetCodecs()->getCodecConfigAndCapabilities(
+ &codec_config, &codecs_local_capabilities,
+ &codecs_selectable_capabilities)) {
+ APPL_TRACE_WARNING(
+ "%s: Peer %s : error reporting audio source codec state: "
+ "cannot get codec config and capabilities",
+ __func__, p_peer->addr.ToString().c_str());
+ return false;
+ }
+ do_in_jni_thread(
+ FROM_HERE,
+ base::Bind(&btif_av_report_source_codec_state, p_peer->addr, codec_config,
+ codecs_local_capabilities, codecs_selectable_capabilities));
+ return true;
+}
+
+void BtaAvCo::DebugDump(int fd) {
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ dprintf(fd, "\nA2DP Codecs and Peers State:\n");
+ dprintf(fd, " Active peer: %s\n",
+ (active_peer_ != nullptr) ? active_peer_->addr.ToString().c_str()
+ : "null");
+
+ for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
+ const BtaAvCoPeer& peer = peers_[i];
+ dprintf(fd, " Peer: %s\n", peer.addr.ToString().c_str());
+ dprintf(fd, " Number of sinks: %u\n", peer.num_sinks);
+ dprintf(fd, " Number of sources: %u\n", peer.num_sources);
+ dprintf(fd, " Number of SEPs: %u\n", peer.num_seps);
+ dprintf(fd, " Number of received sinks: %u\n", peer.num_rx_sinks);
+ dprintf(fd, " Number of received sources: %u\n", peer.num_rx_sources);
+ dprintf(fd, " Number of supported sinks: %u\n", peer.num_sup_sinks);
+ dprintf(fd, " Number of supported sources: %u\n", peer.num_sup_sources);
+ dprintf(fd, " Acceptor: %s\n", (peer.acceptor) ? "true" : "false");
+ dprintf(fd, " Reconfig needed: %s\n",
+ (peer.reconfig_needed) ? "true" : "false");
+ dprintf(fd, " Opened: %s\n", (peer.opened) ? "true" : "false");
+ dprintf(fd, " MTU: %u\n", peer.mtu);
+ dprintf(fd, " UUID to connect: 0x%x\n", peer.uuid_to_connect);
+ dprintf(fd, " BTA AV handle: %u\n", peer.BtaAvHandle());
+ }
+
+ //
+ // Active peer codec-specific stats
+ //
+ if (active_peer_ != nullptr) {
+ A2dpCodecs* a2dp_codecs = active_peer_->GetCodecs();
+ if (a2dp_codecs != nullptr) {
+ a2dp_codecs->debug_codec_dump(fd);
+ }
+ }
+}
+
+bool BtaAvCo::ContentProtectIsScmst(const uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ if (*p_protect_info >= AVDT_CP_LOSC) {
+ uint16_t cp_id;
+ p_protect_info++;
+ STREAM_TO_UINT16(cp_id, p_protect_info);
+ if (cp_id == AVDT_CP_SCMS_T_ID) {
+ APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BtaAvCo::AudioProtectHasScmst(uint8_t num_protect,
+ const uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s", __func__);
+ while (num_protect--) {
+ if (BtaAvCo::ContentProtectIsScmst(p_protect_info)) return true;
+ // Move to the next Content Protect schema
+ p_protect_info += *p_protect_info + 1;
+ }
+ APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__);
+ return false;
+}
+
+bool BtaAvCo::AudioSinkHasContentProtection(const BtaAvCoSep* p_sink) {
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ // Check if content protection is enabled for this stream
+ if (ContentProtectFlag() != AVDT_CP_SCMS_COPY_FREE) {
+ return BtaAvCo::AudioProtectHasScmst(p_sink->num_protect,
+ p_sink->protect_info);
+ }
+
+ APPL_TRACE_DEBUG("%s: not required", __func__);
+ return true;
+}
+
+const BtaAvCoSep* BtaAvCo::FindPeerSourceSepForCurrentCodec(
+ const BtaAvCoPeer* p_peer) {
+ APPL_TRACE_DEBUG("%s: peer num_sup_sources = %d", __func__,
+ p_peer->num_sup_sources);
+
+ for (size_t index = 0; index < p_peer->num_sup_sources; index++) {
+ const uint8_t* p_codec_caps = p_peer->sources[index].codec_caps;
+ if (A2DP_CodecTypeEquals(codec_config_, p_codec_caps) &&
+ A2DP_IsPeerSourceCodecSupported(p_codec_caps)) {
+ return &p_peer->sources[index];
+ }
+ }
+ return nullptr;
+}
+
+BtaAvCoSep* BtaAvCo::SelectSourceCodec(BtaAvCoPeer* p_peer) {
+ BtaAvCoSep* p_sink = nullptr;
+
+ // Update all selectable codecs.
+ // This is needed to update the selectable parameters for each codec.
+ // NOTE: The selectable codec info is used only for informational purpose.
+ for (const auto& iter : p_peer->GetCodecs()->orderedSourceCodecs()) {
+ APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
+ iter->name().c_str());
+ UpdateSelectableCodec(*iter, p_peer);
+ }
+
+ // Select the codec
+ for (const auto& iter : p_peer->GetCodecs()->orderedSourceCodecs()) {
+ APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
+ p_sink = AttemptCodecSelection(*iter, p_peer);
+ if (p_sink != nullptr) {
+ APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
+ break;
+ }
+ APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
+ }
+
+ // NOTE: Unconditionally dispatch the event to make sure a callback with
+ // the most recent codec info is generated.
+ ReportSourceCodecState(p_peer);
+
+ return p_sink;
+}
+
+BtaAvCoSep* BtaAvCo::AttemptCodecSelection(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer) {
+ uint8_t new_codec_config[AVDT_CODEC_SIZE];
+
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ // Find the peer sink for the codec
+ BtaAvCoSep* p_sink = nullptr;
+ for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
+ btav_a2dp_codec_index_t peer_codec_index =
+ A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
+ if (peer_codec_index != codec_config.codecIndex()) {
+ continue;
+ }
+ if (!AudioSinkHasContentProtection(&p_peer->sinks[index])) {
+ APPL_TRACE_DEBUG(
+ "%s: peer sink for codec %s does not support "
+ "Content Protection",
+ __func__, codec_config.name().c_str());
+ continue;
+ }
+ p_sink = &p_peer->sinks[index];
+ break;
+ }
+ if (p_sink == nullptr) {
+ APPL_TRACE_DEBUG("%s: peer sink for codec %s not found", __func__,
+ codec_config.name().c_str());
+ return nullptr;
+ }
+ if (!p_peer->GetCodecs()->setCodecConfig(
+ p_sink->codec_caps, true /* is_capability */, new_codec_config,
+ true /* select_current_codec */)) {
+ APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
+ codec_config.name().c_str());
+ return nullptr;
+ }
+ p_peer->p_sink = p_sink;
+
+ SaveNewCodecConfig(p_peer, new_codec_config, p_sink->num_protect,
+ p_sink->protect_info);
+
+ return p_sink;
+}
+
+bool BtaAvCo::UpdateSelectableCodec(const A2dpCodecConfig& codec_config,
+ BtaAvCoPeer* p_peer) {
+ uint8_t new_codec_config[AVDT_CODEC_SIZE];
+
+ APPL_TRACE_DEBUG("%s", __func__);
+
+ // Find the peer sink for the codec
+ const BtaAvCoSep* p_sink = nullptr;
+ for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
+ btav_a2dp_codec_index_t peer_codec_index =
+ A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
+ if (peer_codec_index != codec_config.codecIndex()) {
+ continue;
+ }
+ if (!AudioSinkHasContentProtection(&p_peer->sinks[index])) {
+ APPL_TRACE_DEBUG(
+ "%s: peer sink for codec %s does not support "
+ "Content Protection",
+ __func__, codec_config.name().c_str());
+ continue;
+ }
+ p_sink = &p_peer->sinks[index];
+ break;
+ }
+ if (p_sink == nullptr) {
+ // The peer sink device does not support this codec
+ return false;
+ }
+ if (!p_peer->GetCodecs()->setCodecConfig(
+ p_sink->codec_caps, true /* is_capability */, new_codec_config,
+ false /* select_current_codec */)) {
+ APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__,
+ codec_config.name().c_str());
+ return false;
+ }
+ return true;
+}
+
+void BtaAvCo::SaveNewCodecConfig(BtaAvCoPeer* p_peer,
+ const uint8_t* new_codec_config,
+ uint8_t num_protect,
+ const uint8_t* p_protect_info) {
+ APPL_TRACE_DEBUG("%s: peer %s", __func__, p_peer->addr.ToString().c_str());
+ A2DP_DumpCodecInfo(new_codec_config);
+
+ std::lock_guard<std::recursive_mutex> lock(codec_lock_);
+
+ memcpy(codec_config_, new_codec_config, sizeof(codec_config_));
+ memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE);
+
+ if (ContentProtectEnabled()) {
+ // Check if this Sink supports SCMS
+ bool cp_active = BtaAvCo::AudioProtectHasScmst(num_protect, p_protect_info);
+ p_peer->SetContentProtectActive(cp_active);
+ }
+}
+
+bool BtaAvCo::SetCodecOtaConfig(BtaAvCoPeer* p_peer,
+ const uint8_t* p_ota_codec_config,
+ uint8_t num_protect,
+ const uint8_t* p_protect_info,
+ bool* p_restart_output) {
uint8_t result_codec_config[AVDT_CODEC_SIZE];
bool restart_input = false;
bool restart_output = false;
bool config_updated = false;
- APPL_TRACE_DEBUG("%s", __func__);
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ p_peer->addr.ToString().c_str());
A2DP_DumpCodecInfo(p_ota_codec_config);
*p_restart_output = false;
@@ -1201,12 +1727,14 @@
APPL_TRACE_WARNING("%s: invalid peer codec config", __func__);
return false;
}
- const tBTA_AV_CO_SINK* p_sink = nullptr;
+ const BtaAvCoSep* p_sink = nullptr;
for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
btav_a2dp_codec_index_t peer_codec_index =
A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
if (peer_codec_index != ota_codec_index) continue;
- if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue;
+ if (!AudioSinkHasContentProtection(&p_peer->sinks[index])) {
+ continue;
+ }
p_sink = &p_peer->sinks[index];
break;
}
@@ -1219,8 +1747,8 @@
}
tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
- bta_av_co_get_peer_params(&peer_params);
- if (!bta_av_co_cb.codecs->setCodecOtaConfig(
+ GetPeerEncoderParameters(p_peer->addr, &peer_params);
+ if (!p_peer->GetCodecs()->setCodecOtaConfig(
p_ota_codec_config, &peer_params, result_codec_config, &restart_input,
&restart_output, &config_updated)) {
APPL_TRACE_ERROR("%s: cannot set OTA config", __func__);
@@ -1233,127 +1761,148 @@
*p_restart_output = true;
p_peer->p_sink = p_sink;
- bta_av_co_save_new_codec_config(p_peer, result_codec_config, num_protect,
- p_protect_info);
+ SaveNewCodecConfig(p_peer, result_codec_config, num_protect,
+ p_protect_info);
}
if (restart_input || config_updated) {
// NOTE: Currently, the input is restarted by sending an upcall
// and informing the Media Framework about the change.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, &p_peer->addr,
- sizeof(RawAddress));
+ ReportSourceCodecState(p_peer);
}
return true;
}
-bool bta_av_co_set_codec_audio_config(
- const btav_a2dp_codec_config_t& codec_audio_config) {
- uint8_t result_codec_config[AVDT_CODEC_SIZE];
- bool restart_output = false;
- bool config_updated = false;
-
- // Find the peer that is currently open
- tBTA_AV_CO_PEER* p_peer = nullptr;
- for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
- tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i];
- if (p_peer_tmp->opened) {
- p_peer = p_peer_tmp;
- break;
- }
- }
- if (p_peer == nullptr) {
- APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
- return false;
- }
-
- // Use the current sink codec
- const tBTA_AV_CO_SINK* p_sink = p_peer->p_sink;
- if (p_sink == nullptr) {
- APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
- return false;
- }
-
- tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
- bta_av_co_get_peer_params(&peer_params);
- if (!bta_av_co_cb.codecs->setCodecAudioConfig(
- codec_audio_config, &peer_params, p_sink->codec_caps,
- result_codec_config, &restart_output, &config_updated)) {
- return false;
- }
-
- if (restart_output) {
- uint8_t num_protect = 0;
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
-#endif
-
- bta_av_co_save_new_codec_config(p_peer, result_codec_config,
- p_sink->num_protect, p_sink->protect_info);
-
- // Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
- if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
- (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved",
- __func__);
- } else {
- APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__,
- p_peer->handle);
- BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx,
- p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
- }
- }
-
- if (config_updated) {
- // NOTE: Currently, the input is restarted by sending an upcall
- // and informing the Media Framework about the change.
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, &p_peer->addr,
- sizeof(RawAddress));
- }
-
- return true;
-}
-
-A2dpCodecs* bta_av_get_a2dp_codecs(void) { return bta_av_co_cb.codecs; }
-
-A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
- A2dpCodecConfig* current_codec;
-
- mutex_global_lock();
- if (bta_av_co_cb.codecs == nullptr) {
- mutex_global_unlock();
- return nullptr;
- }
- current_codec = bta_av_co_cb.codecs->getCurrentCodecConfig();
- mutex_global_unlock();
-
- return current_codec;
-}
-
void bta_av_co_init(
const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
- APPL_TRACE_DEBUG("%s", __func__);
-
- /* Reset the control block */
- bta_av_co_cb.reset();
-
-#if (BTA_AV_CO_CP_SCMS_T == TRUE)
- bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_NEVER);
-#else
- bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_FREE);
-#endif
-
- /* Reset the current config */
- /* Protect access to bta_av_co_cb.codec_config */
- mutex_global_lock();
- bta_av_co_cb.codecs = new A2dpCodecs(codec_priorities);
- bta_av_co_cb.codecs->init();
- A2DP_InitDefaultCodec(bta_av_co_cb.codec_config);
- mutex_global_unlock();
-
- // NOTE: Unconditionally dispatch the event to make sure a callback with
- // the most recent codec info is generated.
- RawAddress empty_raw_address = RawAddress::kEmpty;
- btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, &empty_raw_address,
- sizeof(RawAddress));
+ bta_av_co_cb.Init(codec_priorities);
}
+
+A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
+ return bta_av_co_cb.GetActivePeerCurrentCodec();
+}
+
+bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
+ AvdtpSepConfig* p_cfg) {
+ return A2DP_InitCodecConfig(codec_index, p_cfg);
+}
+
+void bta_av_co_audio_disc_res(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint8_t num_seps,
+ uint8_t num_sinks, uint8_t num_sources,
+ uint16_t uuid_local) {
+ bta_av_co_cb.ProcessDiscoveryResult(bta_av_handle, peer_address, num_seps,
+ num_sinks, num_sources, uuid_local);
+}
+
+tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ uint8_t* p_codec_info,
+ uint8_t* p_sep_info_idx, uint8_t seid,
+ uint8_t* p_num_protect,
+ uint8_t* p_protect_info) {
+ uint16_t peer_uuid = bta_av_co_cb.FindPeerUuid(bta_av_handle);
+
+ APPL_TRACE_DEBUG("%s: peer %s bta_av_handle=0x%x peer_uuid=0x%x", __func__,
+ peer_address.ToString().c_str(), bta_av_handle, peer_uuid);
+
+ switch (peer_uuid) {
+ case UUID_SERVCLASS_AUDIO_SOURCE:
+ return bta_av_co_cb.ProcessSinkGetConfig(
+ bta_av_handle, peer_address, p_codec_info, p_sep_info_idx, seid,
+ p_num_protect, p_protect_info);
+ case UUID_SERVCLASS_AUDIO_SINK:
+ return bta_av_co_cb.ProcessSourceGetConfig(
+ bta_av_handle, peer_address, p_codec_info, p_sep_info_idx, seid,
+ p_num_protect, p_protect_info);
+ default:
+ break;
+ }
+ APPL_TRACE_ERROR("%s: Invalid peer UUID: 0x%x for bta_av_handle 0x%x",
+ peer_uuid, bta_av_handle);
+ return A2DP_FAIL;
+}
+
+void bta_av_co_audio_setconfig(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, uint8_t seid,
+ uint8_t num_protect,
+ const uint8_t* p_protect_info,
+ uint8_t t_local_sep, uint8_t avdt_handle) {
+ bta_av_co_cb.ProcessSetConfig(bta_av_handle, peer_address, p_codec_info, seid,
+ num_protect, p_protect_info, t_local_sep,
+ avdt_handle);
+}
+
+void bta_av_co_audio_open(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ bta_av_co_cb.ProcessOpen(bta_av_handle, peer_address, mtu);
+}
+
+void bta_av_co_audio_close(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ bta_av_co_cb.ProcessClose(bta_av_handle, peer_address);
+}
+
+void bta_av_co_audio_start(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address,
+ const uint8_t* p_codec_info, bool* p_no_rtp_header) {
+ bta_av_co_cb.ProcessStart(bta_av_handle, peer_address, p_codec_info,
+ p_no_rtp_header);
+}
+
+void bta_av_co_audio_stop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ bta_av_co_cb.ProcessStop(bta_av_handle, peer_address);
+}
+
+BT_HDR* bta_av_co_audio_source_data_path(const uint8_t* p_codec_info,
+ uint32_t* p_timestamp) {
+ return bta_av_co_cb.GetNextSourceDataPacket(p_codec_info, p_timestamp);
+}
+
+void bta_av_co_audio_drop(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address) {
+ bta_av_co_cb.DataPacketWasDropped(bta_av_handle, peer_address);
+}
+
+void bta_av_co_audio_delay(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t delay) {
+ bta_av_co_cb.ProcessAudioDelay(bta_av_handle, peer_address, delay);
+}
+
+void bta_av_co_audio_update_mtu(tBTA_AV_HNDL bta_av_handle,
+ const RawAddress& peer_address, uint16_t mtu) {
+ bta_av_co_cb.UpdateMtu(bta_av_handle, peer_address, mtu);
+}
+
+bool bta_av_co_set_active_peer(const RawAddress& peer_address) {
+ return bta_av_co_cb.SetActivePeer(peer_address);
+}
+
+void bta_av_co_get_peer_params(const RawAddress& peer_address,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
+ bta_av_co_cb.GetPeerEncoderParameters(peer_address, p_peer_params);
+}
+
+const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
+ return bta_av_co_cb.GetSourceEncoderInterface();
+}
+
+const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void) {
+ return bta_av_co_cb.GetSinkDecoderInterface();
+}
+
+bool bta_av_co_set_codec_user_config(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config) {
+ return bta_av_co_cb.SetCodecUserConfig(peer_address, codec_user_config);
+}
+
+bool bta_av_co_set_codec_audio_config(
+ const btav_a2dp_codec_config_t& codec_audio_config) {
+ return bta_av_co_cb.SetCodecAudioConfig(codec_audio_config);
+}
+
+void btif_a2dp_codec_debug_dump(int fd) { bta_av_co_cb.DebugDump(fd); }
diff --git a/btif/include/btif_a2dp.h b/btif/include/btif_a2dp.h
index bbc04df..11fd079 100644
--- a/btif/include/btif_a2dp.h
+++ b/btif/include/btif_a2dp.h
@@ -29,11 +29,13 @@
// Process 'start' request from the BTIF state machine to prepare for A2DP
// streaming.
+// |peer_addr| is the peer address.
// |p_av_start| is the data associated with the request - see |tBTA_AV_START|.
// |pending_start| should be set to true if the BTIF state machine is in
// 'pending start' state.
// Returns true if an ACK for the local command was sent, otherwise false.
-bool btif_a2dp_on_started(tBTA_AV_START* p_av_start, bool pending_start);
+bool btif_a2dp_on_started(const RawAddress& peer_addr,
+ tBTA_AV_START* p_av_start, bool pending_start);
// Process 'stop' request from the BTIF state machine to stop A2DP streaming.
// |p_av_suspend| is the data associated with the request - see
diff --git a/btif/include/btif_a2dp_source.h b/btif/include/btif_a2dp_source.h
index 112e1ef..024b5e5 100644
--- a/btif/include/btif_a2dp_source.h
+++ b/btif/include/btif_a2dp_source.h
@@ -46,8 +46,9 @@
bool btif_a2dp_source_is_streaming(void);
// Setup the A2DP Source codec, and prepare the encoder.
+// The peer address is |peer_addr|.
// This function should be called prior to starting A2DP streaming.
-void btif_a2dp_source_setup_codec(void);
+void btif_a2dp_source_setup_codec(const RawAddress& peer_addr);
// Process a request to start the A2DP audio encoding task.
void btif_a2dp_source_start_audio_req(void);
@@ -57,8 +58,10 @@
// Process a request to update the A2DP audio encoder with user preferred
// codec configuration.
+// The peer address is |peer_addr|.
// |codec_user_config| contains the preferred codec user configuration.
void btif_a2dp_source_encoder_user_config_update_req(
+ const RawAddress& peer_addr,
const btav_a2dp_codec_config_t& codec_user_config);
// Process a request to update the A2DP audio encoding with new audio
diff --git a/btif/include/btif_av.h b/btif/include/btif_av.h
index b3dcfca..1f07cd6 100644
--- a/btif/include/btif_av.h
+++ b/btif/include/btif_av.h
@@ -16,177 +16,167 @@
*
******************************************************************************/
-/*******************************************************************************
- *
- * Filename: btif_av.h
- *
- * Description: Main API header file for all BTIF AV functions accessed
- * from internal stack.
- *
- ******************************************************************************/
+/**
+ * BTIF AV API functions accessed internally.
+ */
#ifndef BTIF_AV_H
#define BTIF_AV_H
#include "bta_av_api.h"
#include "btif_common.h"
-#include "btif_sm.h"
-/*******************************************************************************
- * Type definitions for callback functions
- ******************************************************************************/
+/**
+ * When the local device is A2DP source, get the address of the active peer.
+ */
+RawAddress btif_av_source_active_peer(void);
-typedef enum {
- /* Reuse BTA_AV_XXX_EVT - No need to redefine them here */
- BTIF_AV_CONNECT_REQ_EVT = BTA_AV_MAX_EVT,
- BTIF_AV_DISCONNECT_REQ_EVT,
- BTIF_AV_START_STREAM_REQ_EVT,
- BTIF_AV_STOP_STREAM_REQ_EVT,
- BTIF_AV_SUSPEND_STREAM_REQ_EVT,
- BTIF_AV_SOURCE_CONFIG_REQ_EVT,
- BTIF_AV_SOURCE_CONFIG_UPDATED_EVT,
- BTIF_AV_SINK_CONFIG_REQ_EVT,
- BTIF_AV_OFFLOAD_START_REQ_EVT,
- BTIF_AV_CLEANUP_REQ_EVT,
-} btif_av_sm_event_t;
+/**
+ * When the local device is A2DP sink, get the address of the active peer.
+ */
+RawAddress btif_av_sink_active_peer(void);
-/*******************************************************************************
- * BTIF AV API
- ******************************************************************************/
-
-/*******************************************************************************
- *
- * Function btif_av_get_addr
- *
- * Description Fetches current AV BD address
- *
- * Returns BD address
- *
- ******************************************************************************/
-
-RawAddress btif_av_get_addr(void);
-
-/*******************************************************************************
- * Function btif_av_is_sink_enabled
- *
- * Description Checks if A2DP Sink is enabled or not
- *
- * Returns true if A2DP Sink is enabled, false otherwise
- *
- ******************************************************************************/
-
+/**
+ * Check whether A2DP Sink is enabled.
+ */
bool btif_av_is_sink_enabled(void);
-/*******************************************************************************
- *
- * Function btif_av_stream_ready
- *
- * Description Checks whether AV is ready for starting a stream
- *
- * Returns None
- *
- ******************************************************************************/
+/**
+ * Start streaming.
+ */
+void btif_av_stream_start(void);
+/**
+ * Stop streaming.
+ */
+void btif_av_stream_stop(void);
+
+/**
+ * Suspend streaming.
+ */
+void btif_av_stream_suspend(void);
+
+/**
+ * Start offload streaming.
+ */
+void btif_av_stream_start_offload(void);
+
+/**
+ * Check whether ready to start the A2DP stream.
+ */
bool btif_av_stream_ready(void);
-/*******************************************************************************
- *
- * Function btif_av_stream_started_ready
- *
- * Description Checks whether AV ready for media start in streaming state
- *
- * Returns None
- *
- ******************************************************************************/
-
+/**
+ * Check whether the A2DP stream is in started state and ready
+ * for media start.
+ */
bool btif_av_stream_started_ready(void);
-/*******************************************************************************
- *
- * Function btif_dispatch_sm_event
- *
- * Description Send event to AV statemachine
- *
- * Returns None
- *
- ******************************************************************************/
-
-/* used to pass events to AV statemachine from other tasks */
-void btif_dispatch_sm_event(btif_av_sm_event_t event, void* p_data, int len);
-
-/*******************************************************************************
- *
- * Function btif_av_init
- *
- * Description Initializes btif AV if not already done
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
-bt_status_t btif_av_init(int service_id);
-
-/*******************************************************************************
- *
- * Function btif_av_is_connected
- *
- * Description Checks if av has a connected sink
- *
- * Returns bool
- *
- ******************************************************************************/
-
+/**
+ * Check whether there is a connected peer (either Source or Sink)
+ */
bool btif_av_is_connected(void);
-/*******************************************************************************
+/**
+ * Get the Stream Endpoint Type of the Active peer.
*
- * Function btif_av_get_peer_sep
- *
- * Description Get the stream endpoint type.
- *
- * Returns The stream endpoint type: either AVDT_TSEP_SRC or
- * AVDT_TSEP_SNK.
- *
- ******************************************************************************/
-
+ * @return the stream endpoint type: either AVDT_TSEP_SRC or AVDT_TSEP_SNK
+ */
uint8_t btif_av_get_peer_sep(void);
-/*******************************************************************************
- *
- * Function btif_av_is_peer_edr
- *
- * Description Check if the connected a2dp device supports
- * EDR or not. Only when connected this function
- * will accurately provide a true capability of
- * remote peer. If not connected it will always be false.
- *
- * Returns true if remote device is capable of EDR
- *
- ******************************************************************************/
-
-bool btif_av_is_peer_edr(void);
-
-/******************************************************************************
- *
- * Function btif_av_clear_remote_suspend_flag
- *
- * Description Clears remote suspended flag
- *
- * Returns Void
- ******************************************************************************/
+/**
+ * Clear the remote suspended flag for the active peer.
+ */
void btif_av_clear_remote_suspend_flag(void);
-/*******************************************************************************
+/**
+ * Process AVRCP Open event.
*
- * Function btif_av_peer_supports_3mbps
+ * @param peer_address the peer address
+ */
+void btif_av_avrcp_event_open(const RawAddress& peer_address);
+
+/**
+ * Process AVRCP Close event.
*
- * Description Check if the connected A2DP device supports
- * 3 Mbps EDR. This function will only work while connected.
- * If not connected it will always return false.
+ * @param peer_address the peer address
+ */
+void btif_av_avrcp_event_close(const RawAddress& peer_address);
+
+/**
+ * Process AVRCP Remote Play event.
*
- * Returns true if remote device is EDR and supports 3 Mbps
+ * @param peer_address the peer address
+ */
+void btif_av_avrcp_event_remote_play(const RawAddress& peer_address);
+
+/**
+ * Check whether the connected A2DP peer supports EDR.
*
- ******************************************************************************/
-bool btif_av_peer_supports_3mbps(void);
+ * The value can be provided only if the remote peer is connected.
+ * Otherwise, the answer will be always false.
+ *
+ * @param peer_address the peer address
+ * @return true if the remote peer is capable of EDR
+ */
+bool btif_av_is_peer_edr(const RawAddress& peer_address);
+
+/**
+ * Check whether the connected A2DP peer supports 3 Mbps EDR.
+ *
+ * The value can be provided only if the remote peer is connected.
+ * Otherwise, the answer will be always false.
+ *
+ * @param peer_address the peer address
+ * @return true if the remote peer is capable of EDR and supports 3 Mbps
+ */
+bool btif_av_peer_supports_3mbps(const RawAddress& peer_address);
+
+/**
+ * Report A2DP Source Codec State for a peer.
+ *
+ * @param peer_address the address of the peer to report
+ * @param codec_config the codec config to report
+ * @param codecs_local_capabilities the codecs local capabilities to report
+ * @param codecs_selectable_capabilities the codecs selectable capabilities
+ * to report
+ */
+void btif_av_report_source_codec_state(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_config,
+ const std::vector<btav_a2dp_codec_config_t>& codecs_local_capabilities,
+ const std::vector<btav_a2dp_codec_config_t>&
+ codecs_selectable_capabilities);
+
+/**
+ * Initialize / shut down the A2DP Source service.
+ *
+ * @param enable true to enable the A2DP Source service, false to disable it
+ * @return BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
+ */
+bt_status_t btif_av_source_execute_service(bool enable);
+
+/**
+ * Initialize / shut down the A2DP Sink service.
+ *
+ * @param enable true to enable the A2DP Sink service, false to disable it
+ * @return BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
+ */
+bt_status_t btif_av_sink_execute_service(bool enable);
+
+/**
+ * Peer ACL disconnected.
+ *
+ * @param peer_address the disconnected peer address
+ */
+void btif_av_acl_disconnected(const RawAddress& peer_address);
+
+/**
+ * Dump debug-related information for the BTIF AV module.
+ *
+ * @param fd the file descriptor to use for writing the ASCII formatted
+ * information
+ */
+void btif_debug_av_dump(int fd);
#endif /* BTIF_AV_H */
diff --git a/btif/include/btif_av_co.h b/btif/include/btif_av_co.h
index 00fd5b9..0576c27 100644
--- a/btif/include/btif_av_co.h
+++ b/btif/include/btif_av_co.h
@@ -22,14 +22,16 @@
#include "btif/include/btif_a2dp_source.h"
#include "stack/include/a2dp_codec_api.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+// Sets the active peer to |peer_addr|.
+// Returns true on success, otherwise false.
+bool bta_av_co_set_active_peer(const RawAddress& peer_addr);
// Gets the A2DP peer parameters that are used to initialize the encoder.
+// The peer address is |peer_addr|.
// The parameters are stored in |p_peer_params|.
// |p_peer_params| cannot be null.
-void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
+void bta_av_co_get_peer_params(const RawAddress& peer_addr,
+ tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
// Gets the current A2DP encoder interface that can be used to encode and
// prepare A2DP packets for transmission - see |tA2DP_ENCODER_INTERFACE|.
@@ -44,9 +46,11 @@
const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void);
// Sets the user preferred codec configuration.
+// The peer address is |peer_addr|.
// |codec_user_config| contains the preferred codec configuration.
// Returns true on success, otherwise false.
bool bta_av_co_set_codec_user_config(
+ const RawAddress& peer_addr,
const btav_a2dp_codec_config_t& codec_user_config);
// Sets the Audio HAL selected audio feeding parameters.
@@ -61,17 +65,13 @@
void bta_av_co_init(
const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
-// Gets the initialized A2DP codecs.
-// Returns a pointer to the |A2dpCodecs| object with the initialized A2DP
-// codecs, or nullptr if no codecs are initialized.
-A2dpCodecs* bta_av_get_a2dp_codecs(void);
-
-// Gets the current A2DP codec.
+// Gets the current A2DP codec for the active peer.
// Returns a pointer to the current |A2dpCodec| if valid, otherwise nullptr.
A2dpCodecConfig* bta_av_get_a2dp_current_codec(void);
-#ifdef __cplusplus
-}
-#endif
+// Dump A2DP codec debug-related information for the A2DP module.
+// |fd| is the file descriptor to use for writing the ASCII formatted
+// information.
+void btif_a2dp_codec_debug_dump(int fd);
#endif // BTIF_AV_CO_H
diff --git a/btif/include/btif_rc.h b/btif/include/btif_rc.h
new file mode 100644
index 0000000..cd2d0cc
--- /dev/null
+++ b/btif/include/btif_rc.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BTIF_RC_H
+#define BTIF_RC_H
+
+#include "bta_av_api.h"
+
+class RawAddress;
+
+void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data);
+uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr);
+void btif_rc_check_handle_pending_play(const RawAddress& peer_addr,
+ bool bSendToApp);
+bool btif_rc_is_connected_peer(const RawAddress& peer_addr);
+
+#endif // BTIF_RC_H
diff --git a/btif/include/btif_sm.h b/btif/include/btif_sm.h
deleted file mode 100644
index 166745d..0000000
--- a/btif/include/btif_sm.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2009-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
- *
- * Filename: btif_sm.h
- *
- * Description: Generic BTIF state machine API
- *
- *****************************************************************************/
-
-#ifndef BTIF_SM_H
-#define BTIF_SM_H
-
-#include <hardware/bluetooth.h>
-
-#include "stack/include/bt_types.h"
-
-/*****************************************************************************
- * Constants & Macros
- *****************************************************************************/
-
-/* Generic Enter/Exit state machine events */
-#define BTIF_SM_ENTER_EVT 0xFFFF
-#define BTIF_SM_EXIT_EVT 0xFFFE
-
-/*****************************************************************************
- * Type definitions and return values
- *****************************************************************************/
-typedef uint32_t btif_sm_state_t;
-typedef uint32_t btif_sm_event_t;
-typedef void* btif_sm_handle_t;
-typedef bool (*btif_sm_handler_t)(btif_sm_event_t event, void* data);
-
-/*****************************************************************************
- * Functions
- *
- * NOTE: THESE APIs SHOULD BE INVOKED ONLY IN THE BTIF CONTEXT
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * Function btif_sm_init
- *
- * Description Initializes the state machine with the state handlers
- * The caller should ensure that the table and the corresponding
- * states match. The location that 'p_handlers' points to shall
- * be available until the btif_sm_shutdown API is invoked.
- *
- * Returns Returns a pointer to the initialized state machine handle.
- *
- *****************************************************************************/
-btif_sm_handle_t btif_sm_init(const btif_sm_handler_t* p_handlers,
- btif_sm_state_t initial_state);
-
-/*****************************************************************************
- *
- * Function btif_sm_shutdown
- *
- * Description Tears down the state machine
- *
- * Returns None
- *
- *****************************************************************************/
-void btif_sm_shutdown(btif_sm_handle_t handle);
-
-/*****************************************************************************
- *
- * Function btif_sm_get_state
- *
- * Description Fetches the current state of the state machine
- *
- * Returns Current state
- *
- *****************************************************************************/
-btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle);
-
-/*****************************************************************************
- *
- * Function btif_sm_dispatch
- *
- * Description Dispatches the 'event' along with 'data' to the current state
- * handler
- *
- * Returns Returns BT_STATUS_OK on success, BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event,
- void* data);
-
-/*****************************************************************************
- *
- * Function btif_sm_change_state
- *
- * Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT'
- * shall be invoked before exiting the current state. The
- * 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new
- * state
- *
- * Returns Returns BT_STATUS_OK on success, BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_change_state(btif_sm_handle_t handle,
- btif_sm_state_t state);
-
-#endif /* BTIF_SM_H */
diff --git a/btif/include/btif_state_machine.h b/btif/include/btif_state_machine.h
new file mode 100644
index 0000000..49b1583
--- /dev/null
+++ b/btif/include/btif_state_machine.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BTIF_STATE_MACHINE_H
+#define BTIF_STATE_MACHINE_H
+
+#include <map>
+#include <utility>
+
+#include <base/logging.h>
+
+/**
+ * State machine used by BTIF components.
+ */
+class BtifStateMachine {
+ public:
+ enum { kStateInvalid = -1 };
+
+ /**
+ * A class to represent the state in the State Machine.
+ */
+ class State {
+ friend class BtifStateMachine;
+
+ public:
+ /**
+ * Constructor.
+ *
+ * @param sm the State Machine to use
+ * @param state_id the unique State ID. It should be a non-negative number.
+ */
+ State(BtifStateMachine& sm, int state_id) : sm_(sm), state_id_(state_id) {}
+
+ virtual ~State() = default;
+
+ /**
+ * Process an event.
+ * TODO: The arguments are wrong - used for backward compatibility.
+ * Will be replaced later.
+ *
+ * @param event the event type
+ * @param p_data the event data
+ * @return true if the processing was completed, otherwise false
+ */
+ virtual bool ProcessEvent(uint32_t event, void* p_data) = 0;
+
+ /**
+ * Get the State ID.
+ *
+ * @return the State ID
+ */
+ int StateId() const { return state_id_; }
+
+ protected:
+ /**
+ * Called when a state is entered.
+ */
+ virtual void OnEnter() {}
+
+ /**
+ * Called when a state is exited.
+ */
+ virtual void OnExit() {}
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state_id the state ID to transition to. It must be one
+ * of the unique state IDs when the corresponding state was created.
+ */
+ void TransitionTo(int dest_state_id) { sm_.TransitionTo(dest_state_id); }
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state the state to transition to. It cannot be nullptr.
+ */
+ void TransitionTo(BtifStateMachine::State* dest_state) {
+ sm_.TransitionTo(dest_state);
+ }
+
+ private:
+ BtifStateMachine& sm_;
+ int state_id_;
+ };
+
+ BtifStateMachine()
+ : initial_state_(nullptr),
+ previous_state_(nullptr),
+ current_state_(nullptr) {}
+ ~BtifStateMachine() {
+ for (auto& kv : states_) delete kv.second;
+ }
+
+ /**
+ * Start the State Machine operation.
+ */
+ void Start() { TransitionTo(initial_state_); }
+
+ /**
+ * Quit the State Machine operation.
+ */
+ void Quit() { previous_state_ = current_state_ = nullptr; }
+
+ /**
+ * Get the current State ID.
+ *
+ * @return the current State ID
+ */
+ int StateId() const {
+ if (current_state_ != nullptr) {
+ return current_state_->StateId();
+ }
+ return kStateInvalid;
+ }
+
+ /**
+ * Get the previous current State ID.
+ *
+ * @return the previous State ID
+ */
+ int PreviousStateId() const {
+ if (previous_state_ != nullptr) {
+ return previous_state_->StateId();
+ }
+ return kStateInvalid;
+ }
+
+ /**
+ * Process an event.
+ * TODO: The arguments are wrong - used for backward compatibility.
+ * Will be replaced later.
+ *
+ * @param event the event type
+ * @param p_data the event data
+ * @return true if the processing was completed, otherwise false
+ */
+ bool ProcessEvent(uint32_t event, void* p_data) {
+ if (current_state_ == nullptr) return false;
+ return current_state_->ProcessEvent(event, p_data);
+ }
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state_id the state ID to transition to. It must be one
+ * of the unique state IDs when the corresponding state was created.
+ */
+ void TransitionTo(int dest_state_id) {
+ auto it = states_.find(dest_state_id);
+
+ CHECK(it != states_.end()) << "Unknown State ID: " << dest_state_id;
+ State* dest_state = it->second;
+ TransitionTo(dest_state);
+ }
+
+ /**
+ * Transition the State Machine to a new state.
+ *
+ * @param dest_state the state to transition to. It cannot be nullptr.
+ */
+ void TransitionTo(BtifStateMachine::State* dest_state) {
+ if (current_state_ != nullptr) {
+ current_state_->OnExit();
+ }
+ previous_state_ = current_state_;
+ current_state_ = dest_state;
+ current_state_->OnEnter();
+ }
+
+ /**
+ * Add a state to the State Machine.
+ * The state machine takes ownership on the state - i.e., the state will
+ * be deleted by the State Machine itself.
+ *
+ * @param state the state to add
+ */
+ void AddState(State* state) {
+ states_.insert(std::make_pair(state->StateId(), state));
+ }
+
+ /**
+ * Set the initial state of the State Machine.
+ *
+ * @param initial_state the initial state
+ */
+ void SetInitialState(State* initial_state) { initial_state_ = initial_state; }
+
+ private:
+ State* initial_state_;
+ State* previous_state_;
+ State* current_state_;
+ std::map<int, State*> states_;
+};
+
+#endif // BTIF_STATE_MACHINE_H
diff --git a/btif/src/bluetooth.cc b/btif/src/bluetooth.cc
index 89e6802..5d2ffcc 100644
--- a/btif/src/bluetooth.cc
+++ b/btif/src/bluetooth.cc
@@ -50,6 +50,7 @@
#include "bta/include/bta_hf_client_api.h"
#include "btif_a2dp.h"
#include "btif_api.h"
+#include "btif_av.h"
#include "btif_config.h"
#include "btif_debug.h"
#include "btif_debug_btsnoop.h"
@@ -312,6 +313,9 @@
btif_debug_conn_dump(fd);
btif_debug_bond_event_dump(fd);
btif_debug_a2dp_dump(fd);
+ btif_debug_av_dump(fd);
+ bta_debug_av_dump(fd);
+ stack_debug_avdtp_api_dump(fd);
btif_debug_config_dump(fd);
BTA_HfClientDumpStatistics(fd);
wakelock_debug_dump(fd);
diff --git a/btif/src/btif_a2dp.cc b/btif/src/btif_a2dp.cc
index 1888166..e71d895 100644
--- a/btif/src/btif_a2dp.cc
+++ b/btif/src/btif_a2dp.cc
@@ -29,6 +29,7 @@
#include "btif_a2dp_sink.h"
#include "btif_a2dp_source.h"
#include "btif_av.h"
+#include "btif_av_co.h"
#include "btif_util.h"
#include "osi/include/log.h"
@@ -42,7 +43,8 @@
}
}
-bool btif_a2dp_on_started(tBTA_AV_START* p_av_start, bool pending_start) {
+bool btif_a2dp_on_started(const RawAddress& peer_addr,
+ tBTA_AV_START* p_av_start, bool pending_start) {
bool ack = false;
APPL_TRACE_WARNING("## ON A2DP STARTED ##");
@@ -69,7 +71,7 @@
/* We were remotely started, make sure codec
* is setup before datapath is started.
*/
- btif_a2dp_source_setup_codec();
+ btif_a2dp_source_setup_codec(peer_addr);
}
/* media task is autostarted upon a2dp audiopath connection */
@@ -126,4 +128,5 @@
void btif_debug_a2dp_dump(int fd) {
btif_a2dp_source_debug_dump(fd);
btif_a2dp_sink_debug_dump(fd);
+ btif_a2dp_codec_debug_dump(fd);
}
diff --git a/btif/src/btif_a2dp_control.cc b/btif/src/btif_a2dp_control.cc
index b9429ca..51a89e9 100644
--- a/btif/src/btif_a2dp_control.cc
+++ b/btif/src/btif_a2dp_control.cc
@@ -118,7 +118,7 @@
* If we are the source, the ACK will be sent after the start
* procedure is completed, othewise send it now.
*/
- btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_start();
if (btif_av_get_peer_sep() == AVDT_TSEP_SRC)
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
@@ -145,15 +145,14 @@
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
}
-
- btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_stop();
btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
break;
case A2DP_CTRL_CMD_SUSPEND:
/* Local suspend */
if (btif_av_stream_started_ready()) {
- btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_suspend();
break;
}
/* If we are not in started state, just ack back ok and let
@@ -259,7 +258,7 @@
}
case A2DP_CTRL_CMD_OFFLOAD_START:
- btif_dispatch_sm_event(BTIF_AV_OFFLOAD_START_REQ_EVT, NULL, 0);
+ btif_av_stream_start_offload();
break;
default:
@@ -330,7 +329,7 @@
*/
if (btif_a2dp_source_is_streaming()) {
/* Post stop event and wait for audio path to stop */
- btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
+ btif_av_stream_stop();
}
break;
diff --git a/btif/src/btif_a2dp_source.cc b/btif/src/btif_a2dp_source.cc
index ec0612b..5098ea9 100644
--- a/btif/src/btif_a2dp_source.cc
+++ b/btif/src/btif_a2dp_source.cc
@@ -21,6 +21,7 @@
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <base/logging.h>
+#include <base/run_loop.h>
#ifndef OS_GENERIC
#include <cutils/trace.h>
#endif
@@ -40,7 +41,6 @@
#include "osi/include/fixed_queue.h"
#include "osi/include/log.h"
#include "osi/include/metrics.h"
-#include "osi/include/mutex.h"
#include "osi/include/osi.h"
#include "osi/include/thread.h"
#include "osi/include/time.h"
@@ -56,42 +56,22 @@
*/
#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (MAX_PCM_FRAME_NUM_PER_TICK * 2)
-enum {
- BTIF_A2DP_SOURCE_STATE_OFF,
- BTIF_A2DP_SOURCE_STATE_STARTING_UP,
- BTIF_A2DP_SOURCE_STATE_RUNNING,
- BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN
-};
+class SchedulingStats {
+ public:
+ SchedulingStats() { Reset(); }
+ void Reset() {
+ total_updates = 0;
+ last_update_us = 0;
+ overdue_scheduling_count = 0;
+ total_overdue_scheduling_delta_us = 0;
+ max_overdue_scheduling_delta_us = 0;
+ premature_scheduling_count = 0;
+ total_premature_scheduling_delta_us = 0;
+ max_premature_scheduling_delta_us = 0;
+ exact_scheduling_count = 0;
+ total_scheduling_time_us = 0;
+ }
-/* BTIF Media Source event definition */
-enum {
- BTIF_MEDIA_AUDIO_TX_START = 1,
- BTIF_MEDIA_AUDIO_TX_STOP,
- BTIF_MEDIA_AUDIO_TX_FLUSH,
- BTIF_MEDIA_SOURCE_ENCODER_INIT,
- BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE,
- BTIF_MEDIA_AUDIO_FEEDING_UPDATE
-};
-
-/* tBTIF_A2DP_SOURCE_ENCODER_INIT msg structure */
-typedef struct {
- BT_HDR hdr;
- tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
-} tBTIF_A2DP_SOURCE_ENCODER_INIT;
-
-/* tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE msg structure */
-typedef struct {
- BT_HDR hdr;
- btav_a2dp_codec_config_t user_config;
-} tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE;
-
-/* tBTIF_A2DP_AUDIO_FEEDING_UPDATE msg structure */
-typedef struct {
- BT_HDR hdr;
- btav_a2dp_codec_config_t feeding_params;
-} tBTIF_A2DP_AUDIO_FEEDING_UPDATE;
-
-typedef struct {
// Counter for total updates
size_t total_updates;
@@ -121,14 +101,38 @@
// Accumulated and counted scheduling time (in us)
uint64_t total_scheduling_time_us;
-} scheduling_stats_t;
+};
-typedef struct {
+class BtifMediaStats {
+ public:
+ BtifMediaStats() { Reset(); }
+ void Reset() {
+ session_start_us = 0;
+ session_end_us = 0;
+ tx_queue_enqueue_stats.Reset();
+ tx_queue_dequeue_stats.Reset();
+ tx_queue_total_frames = 0;
+ tx_queue_max_frames_per_packet = 0;
+ tx_queue_total_queueing_time_us = 0;
+ tx_queue_max_queueing_time_us = 0;
+ tx_queue_total_readbuf_calls = 0;
+ tx_queue_last_readbuf_us = 0;
+ tx_queue_total_flushed_messages = 0;
+ tx_queue_last_flushed_us = 0;
+ tx_queue_total_dropped_messages = 0;
+ tx_queue_max_dropped_messages = 0;
+ tx_queue_dropouts = 0;
+ tx_queue_last_dropouts_us = 0;
+ media_read_total_underflow_bytes = 0;
+ media_read_total_underflow_count = 0;
+ media_read_last_underflow_us = 0;
+ }
+
uint64_t session_start_us;
uint64_t session_end_us;
- scheduling_stats_t tx_queue_enqueue_stats;
- scheduling_stats_t tx_queue_dequeue_stats;
+ SchedulingStats tx_queue_enqueue_stats;
+ SchedulingStats tx_queue_dequeue_stats;
size_t tx_queue_total_frames;
size_t tx_queue_max_frames_per_packet;
@@ -150,64 +154,171 @@
size_t media_read_total_underflow_bytes;
size_t media_read_total_underflow_count;
uint64_t media_read_last_underflow_us;
-} btif_media_stats_t;
+};
-typedef struct {
- thread_t* worker_thread;
- fixed_queue_t* cmd_msg_queue;
+class BtWorkerThread {
+ public:
+ BtWorkerThread(const std::string& thread_name)
+ : thread_name_(thread_name),
+ message_loop_(nullptr),
+ run_loop_(nullptr),
+ message_loop_thread_(nullptr) {}
+
+ void StartUp() {
+ if (message_loop_thread_ != nullptr) {
+ return; // Already started up
+ }
+ message_loop_ = new base::MessageLoop();
+ run_loop_ = new base::RunLoop();
+ message_loop_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&BtWorkerThread::NotifyStarted, base::Unretained(this)));
+
+ message_loop_thread_ = thread_new_sized(thread_name_.c_str(), SIZE_MAX);
+ CHECK(message_loop_thread_ != nullptr);
+ // TODO: Not needed here - done by raise_priority_a2dp()
+ // thread_set_rt_priority(message_loop_thread_, THREAD_RT_PRIORITY);
+ thread_post(message_loop_thread_, &BtWorkerThread::RunThread, this);
+ }
+
+ bt_status_t DoInThread(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ if ((message_loop_ == nullptr) || !message_loop_->task_runner().get()) {
+ LOG_ERROR(
+ LOG_TAG,
+ "%s: Dropping message for thread %s: message loop is not initialized",
+ __func__, thread_name_.c_str());
+ return BT_STATUS_FAIL;
+ }
+ if (!message_loop_->task_runner()->PostTask(from_here, task)) {
+ LOG_ERROR(LOG_TAG,
+ "%s: Posting task to message loop for thread %s failed",
+ __func__, thread_name_.c_str());
+ return BT_STATUS_FAIL;
+ }
+ return BT_STATUS_SUCCESS;
+ }
+
+ void ShutDown() {
+ if ((run_loop_ != nullptr) && (message_loop_ != nullptr)) {
+ message_loop_->task_runner()->PostTask(FROM_HERE,
+ run_loop_->QuitClosure());
+ }
+ thread_free(message_loop_thread_);
+ message_loop_thread_ = nullptr;
+ }
+
+ void NotifyStarted() {
+ LOG_INFO(LOG_TAG, "%s: message loop for thread %s started", __func__,
+ thread_name_.c_str());
+ }
+
+ void NotifyFinished() {
+ LOG_INFO(LOG_TAG, "%s: message loop for thread %s finished", __func__,
+ thread_name_.c_str());
+ }
+
+ private:
+ static void RunThread(void* context) {
+ BtWorkerThread* wt = static_cast<BtWorkerThread*>(context);
+ wt->Run();
+ }
+
+ void Run() {
+ CHECK(message_loop_ != nullptr);
+ CHECK(run_loop_ != nullptr);
+ run_loop_->Run();
+
+ delete message_loop_;
+ message_loop_ = nullptr;
+ delete run_loop_;
+ run_loop_ = nullptr;
+
+ NotifyFinished();
+ }
+
+ std::string thread_name_;
+ base::MessageLoop* message_loop_;
+ base::RunLoop* run_loop_;
+ thread_t* message_loop_thread_;
+};
+
+class BtifA2dpSource {
+ public:
+ enum RunState {
+ kStateOff,
+ kStateStartingUp,
+ kStateRunning,
+ kStateShuttingDown
+ };
+
+ BtifA2dpSource()
+ : tx_audio_queue(nullptr),
+ tx_flush(false),
+ media_alarm(nullptr),
+ encoder_interface(nullptr),
+ encoder_interval_ms(0),
+ state_(kStateOff) {}
+
+ void Reset() {
+ fixed_queue_free(tx_audio_queue, nullptr);
+ tx_audio_queue = nullptr;
+ tx_flush = false;
+ alarm_free(media_alarm);
+ media_alarm = nullptr;
+ encoder_interface = nullptr;
+ encoder_interval_ms = 0;
+ stats.Reset();
+ accumulated_stats.Reset();
+ state_ = kStateOff;
+ }
+
+ BtifA2dpSource::RunState State() const { return state_; }
+ void SetState(BtifA2dpSource::RunState state) { state_ = state; }
+
fixed_queue_t* tx_audio_queue;
bool tx_flush; /* Discards any outgoing data when true */
alarm_t* media_alarm;
const tA2DP_ENCODER_INTERFACE* encoder_interface;
period_ms_t encoder_interval_ms; /* Local copy of the encoder interval */
- btif_media_stats_t stats;
- btif_media_stats_t accumulated_stats;
-} tBTIF_A2DP_SOURCE_CB;
+ BtifMediaStats stats;
+ BtifMediaStats accumulated_stats;
-static tBTIF_A2DP_SOURCE_CB btif_a2dp_source_cb;
-static int btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF;
+ private:
+ BtifA2dpSource::RunState state_;
+};
-static void btif_a2dp_source_command_ready(fixed_queue_t* queue, void* context);
-static void btif_a2dp_source_startup_delayed(void* context);
-static void btif_a2dp_source_shutdown_delayed(void* context);
+static BtWorkerThread btif_a2dp_source_thread("btif_a2dp_source_thread");
+static BtifA2dpSource btif_a2dp_source_cb;
+
+static void btif_a2dp_source_startup_delayed(void);
+static void btif_a2dp_source_shutdown_delayed(void);
static void btif_a2dp_source_audio_tx_start_event(void);
static void btif_a2dp_source_audio_tx_stop_event(void);
-static void btif_a2dp_source_audio_tx_flush_event(BT_HDR* p_msg);
-static void btif_a2dp_source_encoder_init_event(BT_HDR* p_msg);
-static void btif_a2dp_source_encoder_user_config_update_event(BT_HDR* p_msg);
-static void btif_a2dp_source_audio_feeding_update_event(BT_HDR* p_msg);
-static void btif_a2dp_source_encoder_init(void);
-static void btif_a2dp_source_encoder_init_req(
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_msg);
+static void btif_a2dp_source_audio_tx_flush_event(void);
+static void btif_a2dp_source_encoder_init_event(
+ const tA2DP_ENCODER_INIT_PEER_PARAMS& peer_params,
+ const RawAddress& peer_address);
+static void btif_a2dp_source_encoder_user_config_update_event(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config);
+static void btif_a2dp_source_audio_feeding_update_event(
+ const btav_a2dp_codec_config_t& codec_audio_config);
static bool btif_a2dp_source_audio_tx_flush_req(void);
static void btif_a2dp_source_alarm_cb(void* context);
-static void btif_a2dp_source_audio_handle_timer(void* context);
+static void btif_a2dp_source_audio_handle_timer(void);
static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len);
static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n);
static void log_tstamps_us(const char* comment, uint64_t timestamp_us);
-static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us,
+static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
uint64_t expected_delta);
static void btm_read_rssi_cb(void* data);
static void btm_read_failed_contact_counter_cb(void* data);
static void btm_read_automatic_flush_timeout_cb(void* data);
static void btm_read_tx_power_cb(void* data);
-UNUSED_ATTR static const char* dump_media_event(uint16_t event) {
- switch (event) {
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_START)
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_STOP)
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_FLUSH)
- CASE_RETURN_STR(BTIF_MEDIA_SOURCE_ENCODER_INIT)
- CASE_RETURN_STR(BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE)
- CASE_RETURN_STR(BTIF_MEDIA_AUDIO_FEEDING_UPDATE)
- default:
- break;
- }
- return "UNKNOWN A2DP SOURCE EVENT";
-}
-
-void btif_a2dp_source_accumulate_scheduling_stats(scheduling_stats_t* src,
- scheduling_stats_t* dst) {
+void btif_a2dp_source_accumulate_scheduling_stats(SchedulingStats* src,
+ SchedulingStats* dst) {
dst->total_updates += src->total_updates;
dst->last_update_us = src->last_update_us;
dst->overdue_scheduling_count += src->overdue_scheduling_count;
@@ -226,8 +337,8 @@
dst->total_scheduling_time_us += src->total_scheduling_time_us;
}
-void btif_a2dp_source_accumulate_stats(btif_media_stats_t* src,
- btif_media_stats_t* dst) {
+void btif_a2dp_source_accumulate_stats(BtifMediaStats* src,
+ BtifMediaStats* dst) {
dst->tx_queue_total_frames += src->tx_queue_total_frames;
dst->tx_queue_max_frames_per_packet = std::max(
dst->tx_queue_max_frames_per_packet, src->tx_queue_max_frames_per_packet);
@@ -252,152 +363,103 @@
&dst->tx_queue_enqueue_stats);
btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_dequeue_stats,
&dst->tx_queue_dequeue_stats);
- memset(src, 0, sizeof(btif_media_stats_t));
+ src->Reset();
}
bool btif_a2dp_source_startup(void) {
- if (btif_a2dp_source_state != BTIF_A2DP_SOURCE_STATE_OFF) {
+ if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateOff) {
APPL_TRACE_ERROR("%s: A2DP Source media task already running", __func__);
return false;
}
- memset(&btif_a2dp_source_cb, 0, sizeof(btif_a2dp_source_cb));
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_STARTING_UP;
+ btif_a2dp_source_cb.Reset();
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateStartingUp);
+ btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX);
APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
/* Start A2DP Source media task */
- btif_a2dp_source_cb.worker_thread =
- thread_new_sized("btif_a2dp_source_worker_thread", SIZE_MAX);
- if (btif_a2dp_source_cb.worker_thread == NULL) {
- APPL_TRACE_ERROR("%s: unable to start up media thread", __func__);
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF;
- return false;
- }
-
- btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX);
-
- btif_a2dp_source_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX);
- fixed_queue_register_dequeue(
- btif_a2dp_source_cb.cmd_msg_queue,
- thread_get_reactor(btif_a2dp_source_cb.worker_thread),
- btif_a2dp_source_command_ready, NULL);
+ btif_a2dp_source_thread.StartUp();
APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##");
/* Schedule the rest of the startup operations */
- thread_post(btif_a2dp_source_cb.worker_thread,
- btif_a2dp_source_startup_delayed, NULL);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_startup_delayed));
return true;
}
-static void btif_a2dp_source_startup_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_source_startup_delayed(void) {
raise_priority_a2dp(TASK_HIGH_MEDIA);
btif_a2dp_control_init();
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_RUNNING;
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning);
BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
}
void btif_a2dp_source_shutdown(void) {
- if ((btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) ||
- (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN)) {
+ if ((btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) ||
+ (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown)) {
return;
}
/* Make sure no channels are restarted while shutting down */
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN;
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown);
APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##");
// Stop the timer
alarm_free(btif_a2dp_source_cb.media_alarm);
- btif_a2dp_source_cb.media_alarm = NULL;
+ btif_a2dp_source_cb.media_alarm = nullptr;
// Exit the thread
- fixed_queue_free(btif_a2dp_source_cb.cmd_msg_queue, NULL);
- btif_a2dp_source_cb.cmd_msg_queue = NULL;
- thread_post(btif_a2dp_source_cb.worker_thread,
- btif_a2dp_source_shutdown_delayed, NULL);
- thread_free(btif_a2dp_source_cb.worker_thread);
- btif_a2dp_source_cb.worker_thread = NULL;
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_shutdown_delayed));
+ btif_a2dp_source_thread.ShutDown();
}
-static void btif_a2dp_source_shutdown_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_source_shutdown_delayed(void) {
btif_a2dp_control_cleanup();
- fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, NULL);
- btif_a2dp_source_cb.tx_audio_queue = NULL;
+ fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, nullptr);
+ btif_a2dp_source_cb.tx_audio_queue = nullptr;
- btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF;
+ btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateOff);
BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
}
bool btif_a2dp_source_media_task_is_running(void) {
- return (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_RUNNING);
+ return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning);
}
bool btif_a2dp_source_media_task_is_shutting_down(void) {
- return (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN);
+ return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown);
}
bool btif_a2dp_source_is_streaming(void) {
return alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
}
-static void btif_a2dp_source_command_ready(fixed_queue_t* queue,
- UNUSED_ATTR void* context) {
- BT_HDR* p_msg = (BT_HDR*)fixed_queue_dequeue(queue);
+void btif_a2dp_source_setup_codec(const RawAddress& peer_address) {
+ APPL_TRACE_EVENT("## A2DP SOURCE SETUP CODEC (peer %s) ##",
+ peer_address.ToString().c_str());
- LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event,
- dump_media_event(p_msg->event));
+ // Check to make sure the platform has 8 bits/byte since
+ // we're using that in frame size calculations now.
+ CHECK(CHAR_BIT == 8);
- switch (p_msg->event) {
- case BTIF_MEDIA_AUDIO_TX_START:
- btif_a2dp_source_audio_tx_start_event();
- break;
- case BTIF_MEDIA_AUDIO_TX_STOP:
- btif_a2dp_source_audio_tx_stop_event();
- break;
- case BTIF_MEDIA_AUDIO_TX_FLUSH:
- btif_a2dp_source_audio_tx_flush_event(p_msg);
- break;
- case BTIF_MEDIA_SOURCE_ENCODER_INIT:
- btif_a2dp_source_encoder_init_event(p_msg);
- break;
- case BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE:
- btif_a2dp_source_encoder_user_config_update_event(p_msg);
- break;
- case BTIF_MEDIA_AUDIO_FEEDING_UPDATE:
- btif_a2dp_source_audio_feeding_update_event(p_msg);
- break;
- default:
- APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event);
- break;
- }
-
- osi_free(p_msg);
- LOG_VERBOSE(LOG_TAG, "%s: %s DONE", __func__, dump_media_event(p_msg->event));
-}
-
-void btif_a2dp_source_setup_codec(void) {
- APPL_TRACE_EVENT("## A2DP SOURCE SETUP CODEC ##");
-
- mutex_global_lock();
-
- /* Init the encoding task */
- btif_a2dp_source_encoder_init();
-
- mutex_global_unlock();
+ tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
+ bta_av_co_get_peer_params(peer_address, &peer_params);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_encoder_init_event, peer_params,
+ peer_address));
}
void btif_a2dp_source_start_audio_req(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTIF_MEDIA_AUDIO_TX_START;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
- memset(&btif_a2dp_source_cb.stats, 0, sizeof(btif_media_stats_t));
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_start_event));
+ btif_a2dp_source_cb.stats.Reset();
// Assign session_start_us to 1 when time_get_os_boottime_us() is 0 to
// indicate btif_a2dp_source_start_audio_req() has been called
btif_a2dp_source_cb.stats.session_start_us = time_get_os_boottime_us();
@@ -408,61 +470,28 @@
}
void btif_a2dp_source_stop_audio_req(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_stop_event));
- p_buf->event = BTIF_MEDIA_AUDIO_TX_STOP;
-
- /*
- * Explicitly check whether btif_a2dp_source_cb.cmd_msg_queue is not NULL
- * to avoid a race condition during shutdown of the Bluetooth stack.
- * This race condition is triggered when A2DP audio is streaming on
- * shutdown:
- * "btif_a2dp_source_on_stopped() -> btif_a2dp_source_stop_audio_req()"
- * is called to stop the particular audio stream, and this happens right
- * after the "BTIF_AV_CLEANUP_REQ_EVT -> btif_a2dp_source_shutdown()"
- * processing during the shutdown of the Bluetooth stack.
- */
- if (btif_a2dp_source_cb.cmd_msg_queue != NULL) {
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
- }
btif_a2dp_source_cb.stats.session_end_us = time_get_os_boottime_us();
btif_a2dp_source_update_metrics();
btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
&btif_a2dp_source_cb.accumulated_stats);
}
-static void btif_a2dp_source_encoder_init(void) {
- tBTIF_A2DP_SOURCE_ENCODER_INIT msg;
+static void btif_a2dp_source_encoder_init_event(
+ const tA2DP_ENCODER_INIT_PEER_PARAMS& peer_params,
+ const RawAddress& peer_address) {
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
- // Check to make sure the platform has 8 bits/byte since
- // we're using that in frame size calculations now.
- CHECK(CHAR_BIT == 8);
-
- APPL_TRACE_DEBUG("%s", __func__);
-
- bta_av_co_get_peer_params(&msg.peer_params);
- btif_a2dp_source_encoder_init_req(&msg);
-}
-
-static void btif_a2dp_source_encoder_init_req(
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_msg) {
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_buf =
- (tBTIF_A2DP_SOURCE_ENCODER_INIT*)osi_malloc(
- sizeof(tBTIF_A2DP_SOURCE_ENCODER_INIT));
-
- memcpy(p_buf, p_msg, sizeof(tBTIF_A2DP_SOURCE_ENCODER_INIT));
- p_buf->hdr.event = BTIF_MEDIA_SOURCE_ENCODER_INIT;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
-}
-
-static void btif_a2dp_source_encoder_init_event(BT_HDR* p_msg) {
- tBTIF_A2DP_SOURCE_ENCODER_INIT* p_encoder_init =
- (tBTIF_A2DP_SOURCE_ENCODER_INIT*)p_msg;
-
- APPL_TRACE_DEBUG("%s", __func__);
-
+ if (!bta_av_co_set_active_peer(peer_address)) {
+ APPL_TRACE_ERROR("%s: Cannot stream audio: cannot set active peer to %s",
+ __func__, peer_address.ToString().c_str());
+ return;
+ }
btif_a2dp_source_cb.encoder_interface = bta_av_co_get_encoder_interface();
- if (btif_a2dp_source_cb.encoder_interface == NULL) {
+ if (btif_a2dp_source_cb.encoder_interface == nullptr) {
APPL_TRACE_ERROR("%s: Cannot stream audio: no source encoder interface",
__func__);
return;
@@ -476,8 +505,8 @@
}
btif_a2dp_source_cb.encoder_interface->encoder_init(
- &p_encoder_init->peer_params, a2dp_codec_config,
- btif_a2dp_source_read_callback, btif_a2dp_source_enqueue_callback);
+ &peer_params, a2dp_codec_config, btif_a2dp_source_read_callback,
+ btif_a2dp_source_enqueue_callback);
// Save a local copy of the encoder_interval_ms
btif_a2dp_source_cb.encoder_interval_ms =
@@ -485,50 +514,41 @@
}
void btif_a2dp_source_encoder_user_config_update_req(
+ const RawAddress& peer_address,
const btav_a2dp_codec_config_t& codec_user_config) {
- tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE* p_buf =
- (tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE*)osi_malloc(
- sizeof(tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE));
-
- p_buf->user_config = codec_user_config;
- p_buf->hdr.event = BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_encoder_user_config_update_event,
+ peer_address, codec_user_config));
}
-static void btif_a2dp_source_encoder_user_config_update_event(BT_HDR* p_msg) {
- tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE* p_user_config =
- (tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE*)p_msg;
-
- APPL_TRACE_DEBUG("%s", __func__);
- if (!bta_av_co_set_codec_user_config(p_user_config->user_config)) {
+static void btif_a2dp_source_encoder_user_config_update_event(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_user_config) {
+ APPL_TRACE_DEBUG("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ if (!bta_av_co_set_codec_user_config(peer_address, codec_user_config)) {
APPL_TRACE_ERROR("%s: cannot update codec user configuration", __func__);
}
}
void btif_a2dp_source_feeding_update_req(
const btav_a2dp_codec_config_t& codec_audio_config) {
- tBTIF_A2DP_AUDIO_FEEDING_UPDATE* p_buf =
- (tBTIF_A2DP_AUDIO_FEEDING_UPDATE*)osi_malloc(
- sizeof(tBTIF_A2DP_AUDIO_FEEDING_UPDATE));
-
- p_buf->feeding_params = codec_audio_config;
- p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_UPDATE;
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_feeding_update_event,
+ codec_audio_config));
}
-static void btif_a2dp_source_audio_feeding_update_event(BT_HDR* p_msg) {
- tBTIF_A2DP_AUDIO_FEEDING_UPDATE* p_feeding =
- (tBTIF_A2DP_AUDIO_FEEDING_UPDATE*)p_msg;
-
+static void btif_a2dp_source_audio_feeding_update_event(
+ const btav_a2dp_codec_config_t& codec_audio_config) {
APPL_TRACE_DEBUG("%s", __func__);
- if (!bta_av_co_set_codec_audio_config(p_feeding->feeding_params)) {
+ if (!bta_av_co_set_codec_audio_config(codec_audio_config)) {
APPL_TRACE_ERROR("%s: cannot update codec audio feeding parameters",
__func__);
}
}
void btif_a2dp_source_on_idle(void) {
- if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return;
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
/* Make sure media task is stopped */
btif_a2dp_source_stop_audio_req();
@@ -537,10 +557,10 @@
void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) {
APPL_TRACE_EVENT("## ON A2DP SOURCE STOPPED ##");
- if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return;
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
/* allow using this api for other than suspend */
- if (p_av_suspend != NULL) {
+ if (p_av_suspend != nullptr) {
if (p_av_suspend->status != BTA_AV_SUCCESS) {
APPL_TRACE_EVENT("AV STOP FAILED (%d)", p_av_suspend->status);
if (p_av_suspend->initiator) {
@@ -565,7 +585,7 @@
void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) {
APPL_TRACE_EVENT("## ON A2DP SOURCE SUSPENDED ##");
- if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return;
+ if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return;
/* check for status failures */
if (p_av_suspend->status != BTA_AV_SUCCESS) {
@@ -598,7 +618,7 @@
btif_a2dp_source_is_streaming() ? "true" : "false");
/* Reset the media feeding state */
- CHECK(btif_a2dp_source_cb.encoder_interface != NULL);
+ CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
btif_a2dp_source_cb.encoder_interface->feeding_reset();
APPL_TRACE_EVENT(
@@ -608,14 +628,14 @@
alarm_free(btif_a2dp_source_cb.media_alarm);
btif_a2dp_source_cb.media_alarm =
alarm_new_periodic("btif.a2dp_source_media_alarm");
- if (btif_a2dp_source_cb.media_alarm == NULL) {
+ if (btif_a2dp_source_cb.media_alarm == nullptr) {
LOG_ERROR(LOG_TAG, "%s unable to allocate media alarm", __func__);
return;
}
alarm_set(btif_a2dp_source_cb.media_alarm,
btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(),
- btif_a2dp_source_alarm_cb, NULL);
+ btif_a2dp_source_alarm_cb, nullptr);
}
static void btif_a2dp_source_audio_tx_stop_event(void) {
@@ -628,7 +648,7 @@
/* Stop the timer first */
alarm_free(btif_a2dp_source_cb.media_alarm);
- btif_a2dp_source_cb.media_alarm = NULL;
+ btif_a2dp_source_cb.media_alarm = nullptr;
UIPC_Close(UIPC_CH_ID_AV_AUDIO);
@@ -651,28 +671,28 @@
btif_a2dp_source_cb.tx_flush = false;
/* Reset the media feeding state */
- if (btif_a2dp_source_cb.encoder_interface != NULL)
+ if (btif_a2dp_source_cb.encoder_interface != nullptr)
btif_a2dp_source_cb.encoder_interface->feeding_reset();
}
static void btif_a2dp_source_alarm_cb(UNUSED_ATTR void* context) {
- thread_post(btif_a2dp_source_cb.worker_thread,
- btif_a2dp_source_audio_handle_timer, NULL);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_handle_timer));
}
-static void btif_a2dp_source_audio_handle_timer(UNUSED_ATTR void* context) {
+static void btif_a2dp_source_audio_handle_timer(void) {
uint64_t timestamp_us = time_get_os_boottime_us();
log_tstamps_us("A2DP Source tx timer", timestamp_us);
if (alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
- CHECK(btif_a2dp_source_cb.encoder_interface != NULL);
+ CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
size_t transmit_queue_length =
fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
#ifndef OS_GENERIC
ATRACE_INT("btif TX queue", transmit_queue_length);
#endif
if (btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length !=
- NULL) {
+ nullptr) {
btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length(
transmit_queue_length);
}
@@ -747,7 +767,7 @@
}
// Request additional debug info if we had to flush buffers
- RawAddress peer_bda = btif_av_get_addr();
+ RawAddress peer_bda = btif_av_source_active_peer();
tBTM_STATUS status = BTM_ReadRSSI(peer_bda, btm_read_rssi_cb);
if (status != BTM_CMD_STARTED) {
LOG_WARN(LOG_TAG, "%s: Cannot read RSSI: status %d", __func__, status);
@@ -776,18 +796,18 @@
btif_a2dp_source_cb.stats.tx_queue_total_frames += frames_n;
btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet = std::max(
frames_n, btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet);
- CHECK(btif_a2dp_source_cb.encoder_interface != NULL);
+ CHECK(btif_a2dp_source_cb.encoder_interface != nullptr);
fixed_queue_enqueue(btif_a2dp_source_cb.tx_audio_queue, p_buf);
return true;
}
-static void btif_a2dp_source_audio_tx_flush_event(UNUSED_ATTR BT_HDR* p_msg) {
+static void btif_a2dp_source_audio_tx_flush_event(void) {
/* Flush all enqueued audio buffers (encoded) */
APPL_TRACE_DEBUG("%s", __func__);
- if (btif_a2dp_source_cb.encoder_interface != NULL)
+ if (btif_a2dp_source_cb.encoder_interface != nullptr)
btif_a2dp_source_cb.encoder_interface->feeding_flush();
btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages +=
@@ -796,27 +816,12 @@
time_get_os_boottime_us();
fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free);
- UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, NULL);
+ UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, nullptr);
}
static bool btif_a2dp_source_audio_tx_flush_req(void) {
- BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
- p_buf->event = BTIF_MEDIA_AUDIO_TX_FLUSH;
-
- /*
- * Explicitly check whether the btif_a2dp_source_cb.cmd_msg_queue is not
- * NULL to avoid a race condition during shutdown of the Bluetooth stack.
- * This race condition is triggered when A2DP audio is streaming on
- * shutdown:
- * "btif_a2dp_source_on_stopped() -> btif_a2dp_source_audio_tx_flush_req()"
- * is called to stop the particular audio stream, and this happens right
- * after the "BTIF_AV_CLEANUP_REQ_EVT -> btif_a2dp_source_shutdown()"
- * processing during the shutdown of the Bluetooth stack.
- */
- if (btif_a2dp_source_cb.cmd_msg_queue != NULL)
- fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf);
-
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_audio_tx_flush_event));
return true;
}
@@ -827,7 +832,7 @@
btif_a2dp_source_cb.stats.tx_queue_total_readbuf_calls++;
btif_a2dp_source_cb.stats.tx_queue_last_readbuf_us = now_us;
- if (p_buf != NULL) {
+ if (p_buf != nullptr) {
// Update the statistics
update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_dequeue_stats,
now_us,
@@ -845,7 +850,7 @@
prev_us = timestamp_us;
}
-static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us,
+static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
uint64_t expected_delta) {
uint64_t last_us = stats->last_update_us;
@@ -888,12 +893,9 @@
btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
&btif_a2dp_source_cb.accumulated_stats);
uint64_t now_us = time_get_os_boottime_us();
- btif_media_stats_t* accumulated_stats =
- &btif_a2dp_source_cb.accumulated_stats;
- scheduling_stats_t* enqueue_stats =
- &accumulated_stats->tx_queue_enqueue_stats;
- scheduling_stats_t* dequeue_stats =
- &accumulated_stats->tx_queue_dequeue_stats;
+ BtifMediaStats* accumulated_stats = &btif_a2dp_source_cb.accumulated_stats;
+ SchedulingStats* enqueue_stats = &accumulated_stats->tx_queue_enqueue_stats;
+ SchedulingStats* dequeue_stats = &accumulated_stats->tx_queue_dequeue_stats;
size_t ave_size;
uint64_t ave_time_us;
@@ -1050,53 +1052,45 @@
(unsigned long long)dequeue_stats->max_premature_scheduling_delta_us /
1000,
(unsigned long long)ave_time_us / 1000);
-
- //
- // Codec-specific stats
- //
- A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs();
- if (a2dp_codecs != nullptr) {
- a2dp_codecs->debug_codec_dump(fd);
- }
}
void btif_a2dp_source_update_metrics(void) {
- btif_media_stats_t* stats = &btif_a2dp_source_cb.stats;
- scheduling_stats_t* enqueue_stats = &stats->tx_queue_enqueue_stats;
+ const BtifMediaStats& stats = btif_a2dp_source_cb.stats;
+ const SchedulingStats& enqueue_stats = stats.tx_queue_enqueue_stats;
A2dpSessionMetrics metrics;
// session_start_us is 0 when btif_a2dp_source_start_audio_req() is not called
// mark the metric duration as invalid (-1) in this case
- if (stats->session_start_us != 0) {
- int64_t session_end_us = stats->session_end_us == 0
+ if (stats.session_start_us != 0) {
+ int64_t session_end_us = stats.session_end_us == 0
? time_get_os_boottime_us()
- : stats->session_end_us;
+ : stats.session_end_us;
metrics.audio_duration_ms =
- (session_end_us - stats->session_start_us) / 1000;
+ (session_end_us - stats.session_start_us) / 1000;
}
- if (enqueue_stats->total_updates > 1) {
+ if (enqueue_stats.total_updates > 1) {
metrics.media_timer_min_ms =
btif_a2dp_source_cb.encoder_interval_ms -
- (enqueue_stats->max_premature_scheduling_delta_us / 1000);
+ (enqueue_stats.max_premature_scheduling_delta_us / 1000);
metrics.media_timer_max_ms =
btif_a2dp_source_cb.encoder_interval_ms +
- (enqueue_stats->max_overdue_scheduling_delta_us / 1000);
+ (enqueue_stats.max_overdue_scheduling_delta_us / 1000);
- metrics.total_scheduling_count = enqueue_stats->overdue_scheduling_count +
- enqueue_stats->premature_scheduling_count +
- enqueue_stats->exact_scheduling_count;
+ metrics.total_scheduling_count = enqueue_stats.overdue_scheduling_count +
+ enqueue_stats.premature_scheduling_count +
+ enqueue_stats.exact_scheduling_count;
if (metrics.total_scheduling_count > 0) {
- metrics.media_timer_avg_ms = enqueue_stats->total_scheduling_time_us /
+ metrics.media_timer_avg_ms = enqueue_stats.total_scheduling_time_us /
(1000 * metrics.total_scheduling_count);
}
- metrics.buffer_overruns_max_count = stats->tx_queue_max_dropped_messages;
- metrics.buffer_overruns_total = stats->tx_queue_total_dropped_messages;
- metrics.buffer_underruns_count = stats->media_read_total_underflow_count;
+ metrics.buffer_overruns_max_count = stats.tx_queue_max_dropped_messages;
+ metrics.buffer_overruns_total = stats.tx_queue_total_dropped_messages;
+ metrics.buffer_underruns_count = stats.media_read_total_underflow_count;
metrics.buffer_underruns_average = 0;
if (metrics.buffer_underruns_count > 0) {
metrics.buffer_underruns_average =
- stats->media_read_total_underflow_bytes /
+ stats.media_read_total_underflow_bytes /
metrics.buffer_underruns_count;
}
}
diff --git a/btif/src/btif_av.cc b/btif/src/btif_av.cc
index 7acc23d..03424b5 100644
--- a/btif/src/btif_av.cc
+++ b/btif/src/btif_av.cc
@@ -20,8 +20,11 @@
#include "btif_av.h"
+#include <base/bind.h>
#include <base/logging.h>
+#include <base/strings/stringprintf.h>
#include <string.h>
+#include <map>
#include <hardware/bluetooth.h>
#include <hardware/bt_av.h>
@@ -36,81 +39,432 @@
#include "btif_a2dp_sink.h"
#include "btif_av_co.h"
#include "btif_profile_queue.h"
+#include "btif_rc.h"
+#include "btif_state_machine.h"
#include "btif_util.h"
#include "btu.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
+#include "osi/include/properties.h"
/*****************************************************************************
* Constants & Macros
*****************************************************************************/
-#define BTIF_AV_SERVICE_NAME "Advanced Audio"
-#define BTIF_AVK_SERVICE_NAME "Advanced Audio Sink"
-
-#define BTIF_TIMEOUT_AV_OPEN_ON_RC_MS (2 * 1000)
-
-typedef enum {
- BTIF_AV_STATE_IDLE = 0x0,
- BTIF_AV_STATE_OPENING,
- BTIF_AV_STATE_OPENED,
- BTIF_AV_STATE_STARTED,
- BTIF_AV_STATE_CLOSING
-} btif_av_state_t;
-
-/* Should not need dedicated suspend state as actual actions are no
- different than open state. Suspend flags are needed however to prevent
- media task from trying to restart stream during remote suspend or while
- we are in the process of a local suspend */
-
-#define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
-#define BTIF_AV_FLAG_REMOTE_SUSPEND 0x2
-#define BTIF_AV_FLAG_PENDING_START 0x4
-#define BTIF_AV_FLAG_PENDING_STOP 0x8
+static const std::string kBtifAvSourceServiceName = "Advanced Audio Source";
+static const std::string kBtifAvSinkServiceName = "Advanced Audio Sink";
+static const std::string kBtifAvMaxConnectedAudioDevices =
+ "persist.bluetooth.maxconnectedaudiodevices";
+static constexpr int kDefaultMaxConnectedAudioDevices = 1;
+static constexpr tBTA_AV_HNDL kBtaHandleUnknown = 0;
/*****************************************************************************
* Local type definitions
*****************************************************************************/
typedef struct {
- tBTA_AV_HNDL bta_handle;
- RawAddress peer_bda;
- bool self_initiated_connection;
- btif_sm_handle_t sm_handle;
- uint8_t flags;
- tBTA_AV_EDR edr;
- uint8_t peer_sep; /* sep type of peer device */
- std::vector<btav_a2dp_codec_config_t> codec_priorities;
-} btif_av_cb_t;
-
-typedef struct {
- RawAddress* target_bda;
- uint16_t uuid;
-} btif_av_connect_req_t;
-
-typedef struct {
int sample_rate;
int channel_count;
RawAddress peer_bd;
} btif_av_sink_config_req_t;
+/**
+ * BTIF AV events
+ */
+typedef enum {
+ /* Reuse BTA_AV_XXX_EVT - No need to redefine them here */
+ BTIF_AV_CONNECT_REQ_EVT = BTA_AV_MAX_EVT,
+ BTIF_AV_DISCONNECT_REQ_EVT,
+ BTIF_AV_START_STREAM_REQ_EVT,
+ BTIF_AV_STOP_STREAM_REQ_EVT,
+ BTIF_AV_SUSPEND_STREAM_REQ_EVT,
+ BTIF_AV_SINK_CONFIG_REQ_EVT,
+ BTIF_AV_ACL_DISCONNECTED,
+ BTIF_AV_OFFLOAD_START_REQ_EVT,
+ BTIF_AV_AVRCP_OPEN_EVT,
+ BTIF_AV_AVRCP_CLOSE_EVT,
+ BTIF_AV_AVRCP_REMOTE_PLAY_EVT,
+} btif_av_sm_event_t;
+
+class BtifAvEvent {
+ public:
+ BtifAvEvent(uint32_t event, const void* p_data, size_t data_length);
+ BtifAvEvent(const BtifAvEvent& other);
+ BtifAvEvent() = delete;
+ ~BtifAvEvent();
+ BtifAvEvent& operator=(const BtifAvEvent& other);
+
+ uint32_t Event() const { return event_; }
+ void* Data() const { return data_; }
+ size_t DataLength() const { return data_length_; }
+ std::string ToString() const;
+ static std::string EventName(uint32_t event);
+
+ private:
+ void DeepCopy(uint32_t event, const void* p_data, size_t data_length);
+ void DeepFree();
+
+ uint32_t event_;
+ void* data_;
+ size_t data_length_;
+};
+
+class BtifAvPeer;
+
+// Should not need dedicated Suspend state as actual actions are no
+// different than Open state. Suspend flags are needed however to prevent
+// media task from trying to restart stream during remote Suspend or while
+// we are in the process of a local Suspend.
+class BtifAvStateMachine : public BtifStateMachine {
+ public:
+ enum {
+ kStateIdle, // AVDTP disconnected
+ kStateOpening, // Opening AVDTP connection
+ kStateOpened, // AVDTP is in OPEN state
+ kStateStarted, // A2DP stream started
+ kStateClosing, // Closing AVDTP connection
+ };
+
+ class StateIdle : public State {
+ public:
+ StateIdle(BtifAvStateMachine& sm)
+ : State(sm, kStateIdle), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateOpening : public State {
+ public:
+ StateOpening(BtifAvStateMachine& sm)
+ : State(sm, kStateOpening), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateOpened : public State {
+ public:
+ StateOpened(BtifAvStateMachine& sm)
+ : State(sm, kStateOpened), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateStarted : public State {
+ public:
+ StateStarted(BtifAvStateMachine& sm)
+ : State(sm, kStateStarted), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ class StateClosing : public State {
+ public:
+ StateClosing(BtifAvStateMachine& sm)
+ : State(sm, kStateClosing), peer_(sm.Peer()) {}
+ void OnEnter() override;
+ void OnExit() override;
+ bool ProcessEvent(uint32_t event, void* p_data) override;
+
+ private:
+ BtifAvPeer& peer_;
+ };
+
+ BtifAvStateMachine(BtifAvPeer& btif_av_peer) : peer_(btif_av_peer) {
+ state_idle_ = new StateIdle(*this);
+ state_opening_ = new StateOpening(*this);
+ state_opened_ = new StateOpened(*this);
+ state_started_ = new StateStarted(*this);
+ state_closing_ = new StateClosing(*this);
+
+ AddState(state_idle_);
+ AddState(state_opening_);
+ AddState(state_opened_);
+ AddState(state_started_);
+ AddState(state_closing_);
+ SetInitialState(state_idle_);
+ }
+
+ BtifAvPeer& Peer() { return peer_; }
+
+ private:
+ BtifAvPeer& peer_;
+ StateIdle* state_idle_;
+ StateOpening* state_opening_;
+ StateOpened* state_opened_;
+ StateStarted* state_started_;
+ StateClosing* state_closing_;
+};
+
+class BtifAvPeer {
+ public:
+ enum {
+ kFlagLocalSuspendPending = 0x1,
+ kFlagRemoteSuspend = 0x2,
+ kFlagPendingStart = 0x4,
+ kFlagPendingStop = 0x8,
+ };
+ static constexpr period_ms_t kTimeoutAvOpenOnRcMs = 2 * 1000; // 2s
+
+ BtifAvPeer(const RawAddress& peer_address, uint8_t peer_sep,
+ tBTA_AV_HNDL bta_handle, uint8_t peer_id);
+ ~BtifAvPeer();
+
+ bt_status_t Init();
+ void Cleanup();
+
+ /**
+ * Check whether the peer can be deleted.
+ *
+ * @return true if the pair can be deleted, otherwise false
+ */
+ bool CanBeDeleted() const;
+
+ const RawAddress& PeerAddress() const { return peer_address_; }
+ bool IsSource() const { return (peer_sep_ == AVDT_TSEP_SRC); }
+ bool IsSink() const { return (peer_sep_ == AVDT_TSEP_SNK); }
+ uint8_t PeerSep() const { return peer_sep_; }
+ /**
+ * Get the local device's Service Class UUID
+ *
+ * @return the local device's Service Class UUID: UUID_SERVCLASS_AUDIO_SOURCE
+ * or UUID_SERVCLASS_AUDIO_SINK
+ */
+ uint16_t LocalUuidServiceClass() const {
+ return (IsSink() ? UUID_SERVCLASS_AUDIO_SOURCE : UUID_SERVCLASS_AUDIO_SINK);
+ }
+ tBTA_AV_HNDL BtaHandle() const { return bta_handle_; }
+ void SetBtaHandle(tBTA_AV_HNDL bta_handle) { bta_handle_ = bta_handle; }
+ uint8_t PeerId() const { return peer_id_; }
+
+ BtifAvStateMachine& StateMachine() { return state_machine_; }
+ const BtifAvStateMachine& StateMachine() const { return state_machine_; }
+ alarm_t* AvOpenOnRcTimer() { return av_open_on_rc_timer_; }
+ const alarm_t* AvOpenOnRcTimer() const { return av_open_on_rc_timer_; }
+
+ void SetEdr(tBTA_AV_EDR edr) { edr_ = edr; }
+ bool IsEdr() const { return (edr_ != 0); }
+ bool Is3Mbps() const { return ((edr_ & BTA_AV_EDR_3MBPS) != 0); }
+
+ bool IsConnected() const;
+ bool IsStreaming() const;
+
+ /**
+ * Check whether any of the flags specified by the bitlags mask is set.
+ *
+ * @param bitflags_mask the bitflags to check
+ * @return true if any of the flags to check is set, otherwise false.
+ */
+ bool CheckFlags(uint8_t bitflags_mask) const {
+ return ((flags_ & bitflags_mask) != 0);
+ }
+
+ /**
+ * Set only the flags as specified by the bitflags mask.
+ *
+ * @param bitflags_mask the bitflags to set
+ */
+ void SetFlags(uint8_t bitflags_mask) { flags_ |= bitflags_mask; }
+
+ /**
+ * Clear only the flags as specified by the bitflags mask.
+ *
+ * @param bitflags_mask the bitflags to clear
+ */
+ void ClearFlags(uint8_t bitflags_mask) { flags_ &= ~bitflags_mask; }
+
+ /**
+ * Clear all flags.
+ */
+ void ClearAllFlags() { flags_ = 0; }
+
+ /**
+ * Get a string representation of the flags that are set.
+ */
+ std::string FlagsToString() const;
+
+ bool SelfInitiatedConnection() const { return self_initiated_connection_; }
+ void SetSelfInitiatedConnection(bool v) { self_initiated_connection_ = v; }
+
+ private:
+ const RawAddress peer_address_;
+ const uint8_t peer_sep_; // SEP type of peer device
+ tBTA_AV_HNDL bta_handle_;
+ const uint8_t peer_id_;
+ BtifAvStateMachine state_machine_;
+ alarm_t* av_open_on_rc_timer_;
+ tBTA_AV_EDR edr_;
+ uint8_t flags_;
+ bool self_initiated_connection_;
+};
+
+class BtifAvSource {
+ public:
+ // The PeerId is used as AppId for BTA_AvRegister() purpose
+ static constexpr uint8_t kPeerIdMin = 0;
+ static constexpr uint8_t kPeerIdMax = BTA_AV_NUM_STRS;
+
+ BtifAvSource()
+ : callbacks_(nullptr),
+ enabled_(false),
+ max_connected_peers_(kDefaultMaxConnectedAudioDevices) {}
+ ~BtifAvSource();
+
+ btav_source_callbacks_t* Callbacks() { return callbacks_; }
+ bt_status_t Init(
+ btav_source_callbacks_t* callbacks,
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
+ void Cleanup();
+
+ bool Enabled() const { return enabled_; }
+ BtifAvPeer* FindPeer(const RawAddress& peer_address);
+ BtifAvPeer* FindPeerByHandle(tBTA_AV_HNDL bta_handle);
+ BtifAvPeer* FindPeerByPeerId(uint8_t peer_id);
+ BtifAvPeer* FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle);
+
+ /**
+ * Check whether a connection to a peer is allowed.
+ * The check considers the maximum number of connected peers.
+ *
+ * @param peer_address the peer address to connect to
+ * @return true if connection is allowed, otherwise false
+ */
+ bool AllowedToConnect(const RawAddress& peer_address) const;
+
+ /**
+ * Delete a peer.
+ *
+ * @param peer_address the peer to delete
+ * @return true on success, otherwise false
+ */
+ bool DeletePeer(const RawAddress& peer_address);
+
+ /**
+ * Delete all peers that have transitioned to Idle state and can be deleted.
+ * If a peer was just created/initialized, then it cannot be deleted yet.
+ */
+ void DeleteIdlePeers();
+
+ const RawAddress& ActivePeer() const { return active_peer_; }
+ bool SetActivePeer(const RawAddress& peer_address) {
+ if (active_peer_ == peer_address) return true; // Nothing has changed
+ if (bta_av_co_set_active_peer(peer_address)) {
+ active_peer_ = peer_address;
+ return true;
+ }
+ return false;
+ }
+
+ const std::map<RawAddress, BtifAvPeer*>& Peers() const { return peers_; }
+
+ void RegisterAllBtaHandles();
+ void DeregisterAllBtaHandles();
+ void BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle);
+
+ private:
+ void CleanupAllPeers();
+
+ btav_source_callbacks_t* callbacks_;
+ bool enabled_;
+ int max_connected_peers_;
+ std::map<RawAddress, BtifAvPeer*> peers_;
+ RawAddress active_peer_;
+ std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;
+ std::vector<btav_a2dp_codec_config_t> codec_priorities_;
+};
+
+class BtifAvSink {
+ public:
+ // The PeerId is used as AppId for BTA_AvRegister() purpose
+ static constexpr uint8_t kPeerIdMin = 0;
+ static constexpr uint8_t kPeerIdMax = BTA_AV_NUM_STRS;
+
+ BtifAvSink()
+ : callbacks_(nullptr),
+ enabled_(false),
+ max_connected_peers_(kDefaultMaxConnectedAudioDevices) {}
+ ~BtifAvSink();
+ bt_status_t Init(btav_sink_callbacks_t* callbacks);
+
+ btav_sink_callbacks_t* Callbacks() { return callbacks_; }
+ void Cleanup();
+
+ bool Enabled() const { return enabled_; }
+ BtifAvPeer* FindPeer(const RawAddress& peer_address);
+ BtifAvPeer* FindPeerByHandle(tBTA_AV_HNDL bta_handle);
+ BtifAvPeer* FindPeerByPeerId(uint8_t peer_id);
+ BtifAvPeer* FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle);
+
+ /**
+ * Check whether a connection to a peer is allowed.
+ * The check considers the maximum number of connected peers.
+ *
+ * @param peer_address the peer address to connect to
+ * @return true if connection is allowed, otherwise false
+ */
+ bool AllowedToConnect(const RawAddress& peer_address) const;
+
+ /**
+ * Delete a peer.
+ *
+ * @param peer_address the peer to delete
+ * @return true on success, otherwise false
+ */
+ bool DeletePeer(const RawAddress& peer_address);
+
+ /**
+ * Delete all peers that have transitioned to Idle state and can be deleted.
+ * If a peer was just created/initialized, then it cannot be deleted yet.
+ */
+ void DeleteIdlePeers();
+
+ const RawAddress& ActivePeer() const { return active_peer_; }
+ bool SetActivePeer(const RawAddress& peer_address) {
+ if (bta_av_co_set_active_peer(peer_address)) {
+ active_peer_ = peer_address;
+ return true;
+ }
+ return false;
+ }
+
+ const std::map<RawAddress, BtifAvPeer*>& Peers() const { return peers_; }
+
+ void RegisterAllBtaHandles();
+ void DeregisterAllBtaHandles();
+ void BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle);
+
+ private:
+ void CleanupAllPeers();
+
+ btav_sink_callbacks_t* callbacks_;
+ bool enabled_;
+ int max_connected_peers_;
+ std::map<RawAddress, BtifAvPeer*> peers_;
+ RawAddress active_peer_;
+ std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;
+};
+
/*****************************************************************************
* Static variables
*****************************************************************************/
-static btav_source_callbacks_t* bt_av_src_callbacks = NULL;
-static btav_sink_callbacks_t* bt_av_sink_callbacks = NULL;
-static btif_av_cb_t btif_av_cb = {
- 0, {{0}}, false, 0, 0, 0, 0, std::vector<btav_a2dp_codec_config_t>()};
-static alarm_t* av_open_on_rc_timer = NULL;
-
-/* both interface and media task needs to be ready to alloc incoming request */
-#define CHECK_BTAV_INIT() \
- do { \
- if (((bt_av_src_callbacks == NULL) && (bt_av_sink_callbacks == NULL)) || \
- (btif_av_cb.sm_handle == NULL)) { \
- BTIF_TRACE_WARNING("%s: BTAV not initialized", __func__); \
- return BT_STATUS_NOT_READY; \
- } \
- } while (0)
+static BtifAvSource btif_av_source;
+static BtifAvSink btif_av_sink;
/* Helper macro to avoid code duplication in the state machine handlers */
#define CHECK_RC_EVENT(e, d) \
@@ -126,44 +480,48 @@
btif_rc_handler(e, d); \
} break;
-static bool btif_av_state_idle_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_opening_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_opened_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_started_handler(btif_sm_event_t event, void* data);
-static bool btif_av_state_closing_handler(btif_sm_event_t event, void* data);
+static bt_status_t src_disconnect_sink(const RawAddress& peer_address);
+static bt_status_t sink_disconnect_src(const RawAddress& peer_address);
+static void btif_av_source_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event);
+static void btif_av_sink_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event);
+static void btif_av_handle_event(uint8_t peer_sep,
+ const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle,
+ const BtifAvEvent& btif_av_event);
+static void btif_report_connection_state(const RawAddress& peer_address,
+ btav_connection_state_t state);
+static void btif_report_audio_state(const RawAddress& peer_address,
+ btav_audio_state_t state);
+static void btif_av_source_initiate_av_open_timer_timeout(void* data);
+static void btif_av_sink_initiate_av_open_timer_timeout(void* data);
+static void bta_av_sink_media_callback(tBTA_AV_EVT event,
+ tBTA_AV_MEDIA* p_data);
-static const btif_sm_handler_t btif_av_state_handlers[] = {
- btif_av_state_idle_handler, btif_av_state_opening_handler,
- btif_av_state_opened_handler, btif_av_state_started_handler,
- btif_av_state_closing_handler};
-
-static void btif_av_event_free_data(btif_sm_event_t event, void* p_data);
-
-/*************************************************************************
- * Extern functions
- ************************************************************************/
-extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data);
-extern bool btif_rc_get_connected_peer(RawAddress* peer_addr);
-extern uint8_t btif_rc_get_connected_peer_handle(const RawAddress& peer_addr);
-extern void btif_rc_check_handle_pending_play(const RawAddress& peer_addr,
- bool bSendToApp);
+static BtifAvPeer* btif_av_source_find_peer(const RawAddress& peer_address) {
+ return btif_av_source.FindPeer(peer_address);
+}
+static BtifAvPeer* btif_av_sink_find_peer(const RawAddress& peer_address) {
+ return btif_av_sink.FindPeer(peer_address);
+}
+static BtifAvPeer* btif_av_find_peer(const RawAddress& peer_address) {
+ if (btif_av_source.Enabled()) return btif_av_source_find_peer(peer_address);
+ if (btif_av_sink.Enabled()) return btif_av_sink_find_peer(peer_address);
+ return nullptr;
+}
+static BtifAvPeer* btif_av_find_active_peer() {
+ if (btif_av_source.Enabled())
+ return btif_av_source_find_peer(btif_av_source.ActivePeer());
+ if (btif_av_sink.Enabled())
+ return btif_av_sink_find_peer(btif_av_sink.ActivePeer());
+ return nullptr;
+}
/*****************************************************************************
* Local helper functions
*****************************************************************************/
-const char* dump_av_sm_state_name(btif_av_state_t state) {
- switch (state) {
- CASE_RETURN_STR(BTIF_AV_STATE_IDLE)
- CASE_RETURN_STR(BTIF_AV_STATE_OPENING)
- CASE_RETURN_STR(BTIF_AV_STATE_OPENED)
- CASE_RETURN_STR(BTIF_AV_STATE_STARTED)
- CASE_RETURN_STR(BTIF_AV_STATE_CLOSING)
- default:
- return "UNKNOWN_STATE";
- }
-}
-
const char* dump_av_sm_event_name(btif_av_sm_event_t event) {
switch ((int)event) {
CASE_RETURN_STR(BTA_AV_ENABLE_EVT)
@@ -189,976 +547,67 @@
CASE_RETURN_STR(BTA_AV_REJECT_EVT)
CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
CASE_RETURN_STR(BTA_AV_OFFLOAD_START_RSP_EVT)
- CASE_RETURN_STR(BTIF_SM_ENTER_EVT)
- CASE_RETURN_STR(BTIF_SM_EXIT_EVT)
CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_DISCONNECT_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_START_STREAM_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
- CASE_RETURN_STR(BTIF_AV_SOURCE_CONFIG_REQ_EVT)
- CASE_RETURN_STR(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT)
CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT)
+ CASE_RETURN_STR(BTIF_AV_ACL_DISCONNECTED)
CASE_RETURN_STR(BTIF_AV_OFFLOAD_START_REQ_EVT)
+ CASE_RETURN_STR(BTIF_AV_AVRCP_OPEN_EVT)
+ CASE_RETURN_STR(BTIF_AV_AVRCP_CLOSE_EVT)
+ CASE_RETURN_STR(BTIF_AV_AVRCP_REMOTE_PLAY_EVT)
default:
return "UNKNOWN_EVENT";
}
}
-/****************************************************************************
- * Local helper functions
- ****************************************************************************/
-/*******************************************************************************
- *
- * Function btif_initiate_av_open_timer_timeout
- *
- * Description Timer to trigger AV open if the remote headset establishes
- * RC connection w/o AV connection. The timer is needed to IOP
- * with headsets that do establish AV after RC connection.
- *
- * Returns void
- *
- ******************************************************************************/
-static void btif_initiate_av_open_timer_timeout(UNUSED_ATTR void* data) {
- RawAddress peer_addr;
- btif_av_connect_req_t connect_req;
+BtifAvEvent::BtifAvEvent(uint32_t event, const void* p_data, size_t data_length)
+ : event_(event), data_(nullptr), data_length_(0) {
+ DeepCopy(event, p_data, data_length);
+}
- /* is there at least one RC connection - There should be */
- if (btif_rc_get_connected_peer(&peer_addr)) {
- BTIF_TRACE_DEBUG("%s: Issuing connect to the remote RC peer", __func__);
- /* In case of AVRCP connection request, we will initiate SRC connection */
- connect_req.target_bda = &peer_addr;
- if (bt_av_sink_callbacks != NULL)
- connect_req.uuid = UUID_SERVCLASS_AUDIO_SINK;
- else if (bt_av_src_callbacks != NULL)
- connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
- btif_dispatch_sm_event(BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req,
- sizeof(connect_req));
+BtifAvEvent::BtifAvEvent(const BtifAvEvent& other)
+ : event_(0), data_(nullptr), data_length_(0) {
+ *this = other;
+}
+
+BtifAvEvent& BtifAvEvent::operator=(const BtifAvEvent& other) {
+ DeepFree();
+ DeepCopy(other.Event(), other.Data(), other.DataLength());
+ return *this;
+}
+
+BtifAvEvent::~BtifAvEvent() { DeepFree(); }
+
+std::string BtifAvEvent::ToString() const {
+ return BtifAvEvent::EventName(event_);
+}
+
+std::string BtifAvEvent::EventName(uint32_t event) {
+ std::string name = dump_av_sm_event_name((btif_av_sm_event_t)event);
+ std::stringstream ss_value;
+ ss_value << "(0x" << std::hex << event << ")";
+ return name + ss_value.str();
+}
+
+void BtifAvEvent::DeepCopy(uint32_t event, const void* p_data,
+ size_t data_length) {
+ event_ = event;
+ data_length_ = data_length;
+ if (data_length == 0) {
+ data_ = nullptr;
} else {
- BTIF_TRACE_ERROR("%s: No connected RC peers", __func__);
- }
-}
-
-/*****************************************************************************
- * Static functions
- *****************************************************************************/
-
-/*******************************************************************************
- *
- * Function btif_report_connection_state
- *
- * Description Updates the components via the callbacks about the
- * connection state of a2dp connection.
- *
- * Returns None
- *
- ******************************************************************************/
-static void btif_report_connection_state(RawAddress* bd_addr,
- btav_connection_state_t state) {
- if (bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, connection_state_cb, bd_addr, state);
- } else if (bt_av_src_callbacks != NULL) {
- HAL_CBACK(bt_av_src_callbacks, connection_state_cb, bd_addr, state);
- }
-}
-
-/*******************************************************************************
- *
- * Function btif_report_audio_state
- *
- * Description Updates the components via the callbacks about the audio
- * state of a2dp connection. The state is updated when either
- * the remote ends starts streaming (started state) or whenever
- * it transitions out of started state (to opened or streaming)
- * state.
- *
- * Returns None
- *
- ******************************************************************************/
-static void btif_report_audio_state(RawAddress* bd_addr,
- btav_audio_state_t state) {
- if (bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, audio_state_cb, bd_addr, state);
- } else if (bt_av_src_callbacks != NULL) {
- HAL_CBACK(bt_av_src_callbacks, audio_state_cb, bd_addr, state);
- }
-}
-
-static void btif_update_source_codec(void* p_data) {
- BTIF_TRACE_DEBUG("%s", __func__);
-
- // copy to avoid alignment problems
- btav_a2dp_codec_config_t req;
- memcpy(&req, p_data, sizeof(req));
-
- btif_a2dp_source_encoder_user_config_update_req(req);
-}
-
-static void btif_report_source_codec_state(void* p_data) {
- RawAddress* bd_addr = (RawAddress*)p_data;
- btav_a2dp_codec_config_t codec_config;
- std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
- std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
-
- A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs();
- if (a2dp_codecs == nullptr) return;
- if (!a2dp_codecs->getCodecConfigAndCapabilities(
- &codec_config, &codecs_local_capabilities,
- &codecs_selectable_capabilities)) {
- BTIF_TRACE_WARNING(
- "%s: error reporting audio source codec state: "
- "cannot get codec config and capabilities",
- __func__);
- return;
- }
- if (bt_av_src_callbacks != NULL) {
- HAL_CBACK(bt_av_src_callbacks, audio_config_cb, bd_addr, codec_config,
- codecs_local_capabilities, codecs_selectable_capabilities);
- }
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_idle_handler
- *
- * Description State managing disconnected AV link
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_idle_handler(btif_sm_event_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
- /* clear the peer_bda */
- btif_av_cb.peer_bda = RawAddress::kEmpty;
- btif_av_cb.flags = 0;
- btif_av_cb.edr = 0;
- bta_av_co_init(btif_av_cb.codec_priorities);
- btif_a2dp_on_idle();
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTA_AV_ENABLE_EVT:
- break;
-
- case BTA_AV_REGISTER_EVT:
- btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
- break;
-
- case BTA_AV_PENDING_EVT:
- case BTIF_AV_CONNECT_REQ_EVT: {
- if (event == BTIF_AV_CONNECT_REQ_EVT) {
- btif_av_connect_req_t* connect_req_p = (btif_av_connect_req_t*)p_data;
- btif_av_cb.peer_bda = *connect_req_p->target_bda;
- btif_av_cb.self_initiated_connection = true;
- BTA_AvOpen(btif_av_cb.peer_bda, btif_av_cb.bta_handle, true,
- BTA_SEC_AUTHENTICATE, connect_req_p->uuid);
- } else if (event == BTA_AV_PENDING_EVT) {
- btif_av_cb.peer_bda = ((tBTA_AV*)p_data)->pend.bd_addr;
- btif_av_cb.self_initiated_connection = false;
- if (bt_av_src_callbacks != NULL) {
- BTA_AvOpen(btif_av_cb.peer_bda, btif_av_cb.bta_handle, true,
- BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE);
- }
- if (bt_av_sink_callbacks != NULL) {
- BTA_AvOpen(btif_av_cb.peer_bda, btif_av_cb.bta_handle, true,
- BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SINK);
- }
- }
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
- } break;
-
- case BTA_AV_RC_OPEN_EVT:
- /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it
- * connects. So
- * as per the AV WP, an AVRC connection cannot exist without an AV
- * connection. Therefore,
- * we initiate an AV connection if an RC_OPEN_EVT is received when we are
- * in AV_CLOSED state.
- * We initiate the AV connection after a small 3s timeout to avoid any
- * collisions from the
- * headsets, as some headsets initiate the AVRC connection first and then
- * immediately initiate the AV connection
- *
- * TODO: We may need to do this only on an AVRCP Play. FixMe
- */
-
- BTIF_TRACE_WARNING("%s: BTA_AV_RC_OPEN_EVT received w/o AV", __func__);
- alarm_set_on_mloop(av_open_on_rc_timer, BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
- btif_initiate_av_open_timer_timeout, NULL);
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTA_AV_RC_BROWSE_OPEN_EVT:
- BTIF_TRACE_DEBUG("%s: BTA_AV_RC_BROWSE_OPEN_EVT received", __func__);
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- /*
- * In case Signalling channel is not down
- * and remote started Streaming Procedure
- * we have to handle config and open event in
- * idle_state. We hit these scenarios while running
- * PTS test case for AVRCP Controller
- */
- case BTIF_AV_SINK_CONFIG_REQ_EVT: {
- btif_av_sink_config_req_t req;
- // copy to avoid alignment problems
- memcpy(&req, p_data, sizeof(req));
-
- BTIF_TRACE_WARNING(
- "%s: BTIF_AV_SINK_CONFIG_REQ_EVT sample_rate=%d "
- "channel_count=%d",
- __func__, req.sample_rate, req.channel_count);
- if (bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(req.peer_bd),
- req.sample_rate, req.channel_count);
- }
- } break;
-
- case BTA_AV_OPEN_EVT: {
- tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
- btav_connection_state_t state;
- btif_sm_state_t av_state;
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT status=%d, edr=0x%x", __func__,
- p_bta_data->open.status, p_bta_data->open.edr);
-
- if (p_bta_data->open.status == BTA_AV_SUCCESS) {
- state = BTAV_CONNECTION_STATE_CONNECTED;
- av_state = BTIF_AV_STATE_OPENED;
- btif_av_cb.edr = p_bta_data->open.edr;
-
- btif_av_cb.peer_sep = p_bta_data->open.sep;
- } else {
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT::FAILED status=%d", __func__,
- p_bta_data->open.status);
- state = BTAV_CONNECTION_STATE_DISCONNECTED;
- av_state = BTIF_AV_STATE_IDLE;
- }
-
- /* inform the application of the event */
- btif_report_connection_state(&(btif_av_cb.peer_bda), state);
- /* change state to open/idle based on the status */
- btif_sm_change_state(btif_av_cb.sm_handle, av_state);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* if queued PLAY command, send it now */
- btif_rc_check_handle_pending_play(
- p_bta_data->open.bd_addr,
- (p_bta_data->open.status == BTA_AV_SUCCESS));
- } else if ((btif_av_cb.peer_sep == AVDT_TSEP_SRC) &&
- (p_bta_data->open.status == BTA_AV_SUCCESS)) {
- /* Bring up AVRCP connection too */
- BTA_AvOpenRc(btif_av_cb.bta_handle);
- }
- btif_queue_advance();
- } break;
-
- case BTA_AV_REMOTE_CMD_EVT:
- case BTA_AV_VENDOR_CMD_EVT:
- case BTA_AV_META_MSG_EVT:
- case BTA_AV_RC_FEAT_EVT:
- case BTA_AV_REMOTE_RSP_EVT:
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTA_AV_RC_CLOSE_EVT:
- BTIF_TRACE_DEBUG("%s: BTA_AV_RC_CLOSE_EVT: Stopping AV timer.", __func__);
- alarm_cancel(av_open_on_rc_timer);
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started IDLE",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
-
- return true;
-}
-/*****************************************************************************
- *
- * Function btif_av_state_opening_handler
- *
- * Description Intermediate state managing events during establishment
- * of avdtp channel
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_opening_handler(btif_sm_event_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
- /* inform the application that we are entering connecting state */
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_CONNECTING);
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTA_AV_REJECT_EVT:
- BTIF_TRACE_WARNING("%s: Received BTA_AV_REJECT_EVT", __func__);
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- break;
-
- case BTA_AV_OPEN_EVT: {
- tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
- btav_connection_state_t state;
- btif_sm_state_t av_state;
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT status=%d, edr=0x%x", __func__,
- p_bta_data->open.status, p_bta_data->open.edr);
-
- if (p_bta_data->open.status == BTA_AV_SUCCESS) {
- state = BTAV_CONNECTION_STATE_CONNECTED;
- av_state = BTIF_AV_STATE_OPENED;
- btif_av_cb.edr = p_bta_data->open.edr;
-
- btif_av_cb.peer_sep = p_bta_data->open.sep;
- } else {
- BTIF_TRACE_WARNING("%s: BTA_AV_OPEN_EVT::FAILED status: %d", __func__,
- p_bta_data->open.status);
- RawAddress peer_addr;
- uint8_t peer_handle = BTRC_HANDLE_NONE;
- if (btif_rc_get_connected_peer(&peer_addr) &&
- btif_av_cb.peer_bda == peer_addr) {
- /*
- * Disconnect AVRCP connection, if
- * A2DP conneciton failed, for any reason
- */
- BTIF_TRACE_WARNING("%s: Disconnecting AVRCP: peer_addr=%s", __func__,
- peer_addr.ToString().c_str());
- peer_handle = btif_rc_get_connected_peer_handle(peer_addr);
- if (peer_handle != BTRC_HANDLE_NONE) {
- BTA_AvCloseRc(peer_handle);
- }
- }
- state = BTAV_CONNECTION_STATE_DISCONNECTED;
- av_state = BTIF_AV_STATE_IDLE;
- }
-
- /* inform the application of the event */
- btif_report_connection_state(&(btif_av_cb.peer_bda), state);
- /* change state to open/idle based on the status */
- btif_sm_change_state(btif_av_cb.sm_handle, av_state);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* if queued PLAY command, send it now */
- btif_rc_check_handle_pending_play(
- p_bta_data->open.bd_addr,
- (p_bta_data->open.status == BTA_AV_SUCCESS));
- } else if ((btif_av_cb.peer_sep == AVDT_TSEP_SRC) &&
- (p_bta_data->open.status == BTA_AV_SUCCESS)) {
- /* Bring up AVRCP connection too */
- BTA_AvOpenRc(btif_av_cb.bta_handle);
- }
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- } break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- case BTIF_AV_SINK_CONFIG_REQ_EVT: {
- btif_av_sink_config_req_t req;
- // copy to avoid alignment problems
- memcpy(&req, p_data, sizeof(req));
-
- BTIF_TRACE_WARNING(
- "%s: BTIF_AV_SINK_CONFIG_REQ_EVT sample_rate=%d "
- "channel_count=%d",
- __func__, req.sample_rate, req.channel_count);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC &&
- bt_av_sink_callbacks != NULL) {
- HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb.peer_bda),
- req.sample_rate, req.channel_count);
- }
- } break;
-
- case BTIF_AV_CONNECT_REQ_EVT: {
- // Check for device, if same device which moved to opening then ignore
- // callback
- btif_av_connect_req_t* connect_req_p = (btif_av_connect_req_t*)p_data;
- RawAddress& target_bda = *connect_req_p->target_bda;
- if (btif_av_cb.peer_bda == target_bda) {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, ignore Connect request",
- __func__, btif_av_cb.peer_bda.ToString().c_str());
- } else {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, reject Connect request to %s",
- __func__, btif_av_cb.peer_bda.ToString().c_str(),
- target_bda.ToString().c_str());
- btif_report_connection_state(&target_bda,
- BTAV_CONNECTION_STATE_DISCONNECTED);
- }
- // Ignore all connection request if we are already opening
- btif_queue_advance();
- } break;
-
- case BTA_AV_PENDING_EVT: {
- // Check for device, if same device which moved to opening then ignore
- // callback
- const RawAddress& bd_addr = ((tBTA_AV*)p_data)->pend.bd_addr;
- if (bd_addr == btif_av_cb.peer_bda) {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, ignore incoming request",
- __func__, btif_av_cb.peer_bda.ToString().c_str());
- } else {
- BTIF_TRACE_WARNING(
- "%s: device %s is already connecting, reject incoming request "
- "from %s",
- __func__, btif_av_cb.peer_bda.ToString().c_str(),
- bd_addr.ToString().c_str());
- BTA_AvDisconnect(bd_addr);
- }
- } break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started OPENING",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- case BTA_AV_CLOSE_EVT:
- btif_a2dp_on_stopped(NULL);
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- break;
-
- case BTIF_AV_DISCONNECT_REQ_EVT:
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
- BTA_AvClose(btif_av_cb.bta_handle);
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- if (btif_av_cb.self_initiated_connection) {
- btif_queue_advance();
- }
- break;
-
- CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
- return true;
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_closing_handler
- *
- * Description Intermediate state managing events during closing
- * of avdtp channel
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_closing_handler(btif_sm_event_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* immediately stop transmission of frames */
- btif_a2dp_source_set_tx_flush(true);
- /* wait for audioflinger to stop a2dp */
- }
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- btif_a2dp_sink_set_rx_flush(true);
- }
- break;
-
- case BTA_AV_STOP_EVT:
- case BTIF_AV_STOP_STREAM_REQ_EVT:
- btif_a2dp_on_stopped(NULL);
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- case BTA_AV_CLOSE_EVT:
-
- /* inform the application that we are disconnecting */
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
-
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- break;
-
- /* Handle the RC_CLOSE event for the cleanup */
- case BTA_AV_RC_CLOSE_EVT:
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- /* Handle the RC_BROWSE_CLOSE event for tetsing*/
- case BTA_AV_RC_BROWSE_CLOSE_EVT:
- btif_rc_handler(event, (tBTA_AV*)p_data);
- break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Closing",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
- return true;
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_opened_handler
- *
- * Description Handles AV events while AVDTP is in OPEN state
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_opened_handler(btif_sm_event_t event, void* p_data) {
- tBTA_AV* p_av = (tBTA_AV*)p_data;
-
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- if ((event == BTA_AV_REMOTE_CMD_EVT) &&
- (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) &&
- (p_av->remote_cmd.rc_id == AVRC_ID_PLAY)) {
- BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY", __func__);
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+ data_ = osi_malloc(data_length_);
+ memcpy(data_, p_data, data_length);
}
switch (event) {
- case BTIF_SM_ENTER_EVT:
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- break;
-
- case BTIF_SM_EXIT_EVT:
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- break;
-
- case BTIF_AV_START_STREAM_REQ_EVT:
- if (btif_av_cb.peer_sep != AVDT_TSEP_SRC) btif_a2dp_source_setup_codec();
- BTA_AvStart();
- btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
- break;
-
- case BTA_AV_START_EVT: {
- BTIF_TRACE_WARNING(
- "%s: BTA_AV_START_EVT status=%d suspending=%d initiator=%d "
- "flags=0x%x",
- __func__, p_av->start.status, p_av->start.suspending,
- p_av->start.initiator, btif_av_cb.flags);
-
- if ((p_av->start.status == BTA_SUCCESS) && p_av->start.suspending)
- return true;
-
- /* if remote tries to start a2dp when DUT is a2dp source
- * then suspend. In case a2dp is sink and call is active
- * then disconnect the AVDTP channel
- */
- if (!(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)) {
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- BTIF_TRACE_WARNING("%s: trigger suspend as remote initiated!!",
- __func__);
- btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
- }
- }
-
- /* In case peer is A2DP SRC we do not want to ack commands on UIPC*/
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- if (btif_a2dp_on_started(
- &p_av->start,
- ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0))) {
- /* only clear pending flag after acknowledgement */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- }
- }
-
- /* remain in open state if status failed */
- if (p_av->start.status != BTA_AV_SUCCESS) return false;
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- btif_a2dp_sink_set_rx_flush(
- false); /* remove flush state, ready for streaming*/
- }
-
- /* change state to started, send acknowledgement if start is pending */
- if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
- btif_a2dp_on_started(NULL, true);
- /* pending start flag will be cleared when exit current state */
- }
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED);
-
- } break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- case BTIF_AV_DISCONNECT_REQ_EVT:
- BTA_AvClose(btif_av_cb.bta_handle);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- BTA_AvCloseRc(btif_av_cb.bta_handle);
- }
-
- /* inform the application that we are disconnecting */
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTING);
- break;
-
- case BTA_AV_CLOSE_EVT:
- /* avdtp link is closed */
- btif_a2dp_on_stopped(NULL);
-
- /* inform the application that we are disconnected */
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
-
- /* change state to idle, send acknowledgement if start is pending */
- if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
- btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
- /* pending start flag will be cleared when exit current state */
- }
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- break;
-
- case BTA_AV_RECONFIG_EVT:
- if ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
- (p_av->reconfig.status == BTA_AV_SUCCESS)) {
- APPL_TRACE_WARNING("reconfig done BTA_AVstart()");
- BTA_AvStart();
- } else if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
- btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
- btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
- }
- break;
-
- case BTIF_AV_CONNECT_REQ_EVT: {
- btif_av_connect_req_t* connect_req_p = (btif_av_connect_req_t*)p_data;
- RawAddress& target_bda = *connect_req_p->target_bda;
- if (btif_av_cb.peer_bda == target_bda) {
- BTIF_TRACE_WARNING(
- "%s: Ignore BTIF_AV_CONNECT_REQ_EVT for same device: target_bda=%s",
- __func__, target_bda.ToString().c_str());
- } else {
- BTIF_TRACE_WARNING(
- "%s: Moved to opened by Other incoming Connect request: "
- "target_bda=%s",
- __func__, target_bda.ToString().c_str());
- btif_report_connection_state(&target_bda,
- BTAV_CONNECTION_STATE_DISCONNECTED);
- }
- btif_queue_advance();
- } break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTIF_TRACE_ERROR(
- "%s: BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Opened",
- __func__);
- btif_a2dp_on_offload_started(BTA_AV_FAIL);
- break;
-
- CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
- return true;
-}
-
-/*****************************************************************************
- *
- * Function btif_av_state_started_handler
- *
- * Description Handles AV events while A2DP stream is started
- *
- * Returns true if event was processed, false otherwise
- *
- ******************************************************************************/
-
-static bool btif_av_state_started_handler(btif_sm_event_t event, void* p_data) {
- tBTA_AV* p_av = (tBTA_AV*)p_data;
-
- BTIF_TRACE_DEBUG("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- switch (event) {
- case BTIF_SM_ENTER_EVT:
-
- /* we are again in started state, clear any remote suspend flags */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-
- /**
- * Report to components above that we have entered the streaming
- * stage, this should usually be followed by focus grant.
- * see update_audio_focus_state()
- */
- btif_report_audio_state(&(btif_av_cb.peer_bda), BTAV_AUDIO_STATE_STARTED);
- break;
-
- case BTIF_SM_EXIT_EVT:
- break;
-
- case BTIF_AV_START_STREAM_REQ_EVT:
- /* we were remotely started, just ack back the local request */
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
- btif_a2dp_on_started(NULL, true);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_REQ_EVT:
- btif_update_source_codec(p_data);
- break;
-
- case BTIF_AV_SOURCE_CONFIG_UPDATED_EVT:
- btif_report_source_codec_state(p_data);
- break;
-
- /* fixme -- use suspend = true always to work around issue with BTA AV */
- case BTIF_AV_STOP_STREAM_REQ_EVT:
- case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
- /* set pending flag to ensure btif task is not trying to restart
- stream while suspend is in progress */
- btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
-
- /* if we were remotely suspended but suspend locally, local suspend
- always overrides */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /*
- * Immediately stop transmission of frames while suspend is
- * pending.
- */
- btif_a2dp_source_set_tx_flush(true);
- }
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- btif_a2dp_on_stopped(NULL);
- }
-
- BTA_AvStop(true);
- break;
-
- case BTIF_AV_DISCONNECT_REQ_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- /* request avdtp to close */
- BTA_AvClose(btif_av_cb.bta_handle);
- if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
- BTA_AvCloseRc(btif_av_cb.bta_handle);
- }
-
- /* inform the application that we are disconnecting */
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTING);
-
- /* wait in closing state until fully closed */
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
- break;
-
- case BTA_AV_SUSPEND_EVT:
- BTIF_TRACE_WARNING(
- "%s: BTA_AV_SUSPEND_EVT status=%d initiator=%d flags=0x%x", __func__,
- p_av->suspend.status, p_av->suspend.initiator, btif_av_cb.flags);
-
- /* a2dp suspended, stop media task until resumed */
- btif_a2dp_on_suspended(&p_av->suspend);
-
- /* if not successful, remain in current state */
- if (p_av->suspend.status != BTA_AV_SUCCESS) {
- btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
-
- if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
- /* suspend failed, reset back tx flush state */
- btif_a2dp_source_set_tx_flush(false);
- }
- return false;
- }
-
- if (p_av->suspend.initiator != true) {
- /* remote suspend, notify HAL and await audioflinger to
- suspend/stop stream */
-
- /* set remote suspend flag to block media task from restarting
- stream only if we did not already initiate a local suspend */
- if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
- btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
-
- btif_report_audio_state(&(btif_av_cb.peer_bda),
- BTAV_AUDIO_STATE_REMOTE_SUSPEND);
- } else {
- btif_report_audio_state(&(btif_av_cb.peer_bda),
- BTAV_AUDIO_STATE_STOPPED);
- }
-
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
-
- /* suspend completed and state changed, clear pending status */
- btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
- break;
-
- case BTA_AV_STOP_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
- btif_a2dp_on_stopped(&p_av->suspend);
-
- btif_report_audio_state(&(btif_av_cb.peer_bda), BTAV_AUDIO_STATE_STOPPED);
-
- /* if stop was successful, change state to open */
- if (p_av->suspend.status == BTA_AV_SUCCESS)
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
-
- break;
-
- case BTA_AV_CLOSE_EVT:
- BTIF_TRACE_WARNING("%s: event=%s flags=0x%x", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event),
- btif_av_cb.flags);
-
- btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
-
- /* avdtp link is closed */
- btif_a2dp_on_stopped(NULL);
-
- /* inform the application that we are disconnected */
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
-
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
- break;
-
- case BTIF_AV_OFFLOAD_START_REQ_EVT:
- BTA_AvOffloadStart(btif_av_cb.bta_handle);
- break;
-
- case BTA_AV_OFFLOAD_START_RSP_EVT:
- btif_a2dp_on_offload_started(p_av->status);
- break;
-
- CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
-
- default:
- BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- return false;
- }
-
- return true;
-}
-
-/*****************************************************************************
- * Local event handlers
- *****************************************************************************/
-
-static void btif_av_handle_event(uint16_t event, char* p_param) {
- BTIF_TRACE_EVENT("%s: event=%s", __func__,
- dump_av_sm_event_name((btif_av_sm_event_t)event));
- switch (event) {
- case BTIF_AV_CLEANUP_REQ_EVT:
- btif_a2dp_source_shutdown();
- btif_a2dp_sink_shutdown();
- break;
-
- case BTA_AV_REGISTER_EVT:
- if (btif_av_cb.sm_handle == NULL) {
- btif_av_cb.bta_handle = ((tBTA_AV*)p_param)->registr.hndl;
- BTIF_TRACE_DEBUG("%s: BTA AV Handle updated", __func__);
- }
- /* FALLTHROUGH */
- default:
- btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);
- btif_av_event_free_data(event, p_param);
- }
-}
-
-void btif_av_event_deep_copy(uint16_t event, char* p_dest, char* p_src) {
- BTIF_TRACE_DEBUG("%s", __func__);
- tBTA_AV* av_src = (tBTA_AV*)p_src;
- tBTA_AV* av_dest = (tBTA_AV*)p_dest;
-
- // First copy the structure
- maybe_non_aligned_memcpy(av_dest, av_src, sizeof(*av_src));
- switch (event) {
- case BTA_AV_META_MSG_EVT:
+ case BTA_AV_META_MSG_EVT: {
+ CHECK(data_length >= sizeof(tBTA_AV));
+ const tBTA_AV* av_src = (const tBTA_AV*)p_data;
+ tBTA_AV* av_dest = (tBTA_AV*)data_;
if (av_src->meta_msg.p_data && av_src->meta_msg.len) {
av_dest->meta_msg.p_data = (uint8_t*)osi_calloc(av_src->meta_msg.len);
memcpy(av_dest->meta_msg.p_data, av_src->meta_msg.p_data,
@@ -1181,17 +630,17 @@
p_msg_src->vendor.p_vendor_data, p_msg_src->vendor.vendor_len);
}
}
- break;
+ } break;
default:
break;
}
}
-static void btif_av_event_free_data(btif_sm_event_t event, void* p_data) {
- switch (event) {
+void BtifAvEvent::DeepFree() {
+ switch (event_) {
case BTA_AV_META_MSG_EVT: {
- tBTA_AV* av = (tBTA_AV*)p_data;
+ tBTA_AV* av = (tBTA_AV*)data_;
osi_free_and_reset((void**)&av->meta_msg.p_data);
if (av->meta_msg.p_msg) {
@@ -1205,46 +654,1663 @@
default:
break;
}
+
+ osi_free_and_reset((void**)&data_);
+ data_length_ = 0;
}
-static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
- btif_transfer_context(btif_av_handle_event, event, (char*)p_data,
- sizeof(tBTA_AV), btif_av_event_deep_copy);
+BtifAvPeer::BtifAvPeer(const RawAddress& peer_address, uint8_t peer_sep,
+ tBTA_AV_HNDL bta_handle, uint8_t peer_id)
+ : peer_address_(peer_address),
+ peer_sep_(peer_sep),
+ bta_handle_(bta_handle),
+ peer_id_(peer_id),
+ state_machine_(*this),
+ av_open_on_rc_timer_(nullptr),
+ edr_(0),
+ flags_(0),
+ self_initiated_connection_(false) {}
+
+BtifAvPeer::~BtifAvPeer() { alarm_free(av_open_on_rc_timer_); }
+
+std::string BtifAvPeer::FlagsToString() const {
+ std::string result;
+
+ if (flags_ & BtifAvPeer::kFlagLocalSuspendPending) {
+ if (!result.empty()) result += "|";
+ result += "LOCAL_SUSPEND_PENDING";
+ }
+ if (flags_ & BtifAvPeer::kFlagRemoteSuspend) {
+ if (!result.empty()) result += "|";
+ result += "REMOTE_SUSPEND";
+ }
+ if (flags_ & BtifAvPeer::kFlagPendingStart) {
+ if (!result.empty()) result += "|";
+ result += "PENDING_START";
+ }
+ if (flags_ & BtifAvPeer::kFlagPendingStop) {
+ if (!result.empty()) result += "|";
+ result += "PENDING_STOP";
+ }
+ if (result.empty()) result = "None";
+
+ return base::StringPrintf("0x%x(%s)", flags_, result.c_str());
}
-static void bte_av_sink_media_callback(tBTA_AV_EVT event,
+bt_status_t BtifAvPeer::Init() {
+ alarm_free(av_open_on_rc_timer_);
+ av_open_on_rc_timer_ = alarm_new("btif_av_peer.av_open_on_rc_timer");
+
+ state_machine_.Start();
+ return BT_STATUS_SUCCESS;
+}
+
+void BtifAvPeer::Cleanup() {
+ state_machine_.Quit();
+ alarm_free(av_open_on_rc_timer_);
+ av_open_on_rc_timer_ = nullptr;
+}
+
+bool BtifAvPeer::CanBeDeleted() const {
+ return (
+ (state_machine_.StateId() == BtifAvStateMachine::kStateIdle) &&
+ (state_machine_.PreviousStateId() != BtifAvStateMachine::kStateInvalid));
+}
+
+bool BtifAvPeer::IsConnected() const {
+ int state = state_machine_.StateId();
+ return ((state == BtifAvStateMachine::kStateOpened) ||
+ (state == BtifAvStateMachine::kStateStarted));
+}
+
+bool BtifAvPeer::IsStreaming() const {
+ int state = state_machine_.StateId();
+ return (state == BtifAvStateMachine::kStateStarted);
+}
+
+BtifAvSource::~BtifAvSource() { CleanupAllPeers(); }
+
+bt_status_t BtifAvSource::Init(
+ btav_source_callbacks_t* callbacks,
+ const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
+ if (enabled_) return BT_STATUS_SUCCESS;
+
+ CleanupAllPeers();
+ max_connected_peers_ =
+ osi_property_get_int32(kBtifAvMaxConnectedAudioDevices.c_str(),
+ kDefaultMaxConnectedAudioDevices);
+ callbacks_ = callbacks;
+ codec_priorities_ = codec_priorities;
+ bta_av_co_init(codec_priorities_);
+
+ if (!btif_a2dp_source_startup()) {
+ return BT_STATUS_FAIL; // Already running
+ }
+ btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
+ enabled_ = true;
+ return BT_STATUS_SUCCESS;
+}
+
+void BtifAvSource::Cleanup() {
+ if (!enabled_) return;
+
+ btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE);
+ do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_source_shutdown));
+
+ btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
+ CleanupAllPeers();
+
+ callbacks_ = nullptr;
+ enabled_ = false;
+}
+
+BtifAvPeer* BtifAvSource::FindPeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it != peers_.end()) return it->second;
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSource::FindPeerByHandle(tBTA_AV_HNDL bta_handle) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->BtaHandle() == bta_handle) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSource::FindPeerByPeerId(uint8_t peer_id) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->PeerId() == peer_id) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSource::FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle) {
+ BtifAvPeer* peer = FindPeer(peer_address);
+ if (peer != nullptr) return peer;
+
+ // Find next availabie Peer ID to use
+ uint8_t peer_id;
+ for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ if (FindPeerByPeerId(peer_id) == nullptr) break;
+ }
+ if (peer_id == kPeerIdMax) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot create peer for peer_address=%s : "
+ "cannot allocate unique Peer ID",
+ __PRETTY_FUNCTION__, peer_address.ToString().c_str());
+ return nullptr;
+ }
+
+ // Get the BTA Handle (if known)
+ if (bta_handle == kBtaHandleUnknown) {
+ auto it = peer_id2bta_handle_.find(peer_id);
+ if (it != peer_id2bta_handle_.end()) {
+ bta_handle = it->second;
+ }
+ }
+
+ peer = new BtifAvPeer(peer_address, AVDT_TSEP_SNK, bta_handle, peer_id);
+ peers_.insert(std::make_pair(peer_address, peer));
+ peer->Init();
+ return peer;
+}
+
+bool BtifAvSource::AllowedToConnect(const RawAddress& peer_address) const {
+ int connected = 0;
+
+ // Count peers that are in the process of connecting or already connected
+ for (auto it : peers_) {
+ const BtifAvPeer* peer = it.second;
+ switch (peer->StateMachine().StateId()) {
+ case BtifAvStateMachine::kStateOpening:
+ case BtifAvStateMachine::kStateOpened:
+ case BtifAvStateMachine::kStateStarted:
+ if (peer->PeerAddress() == peer_address) {
+ return true; // Already connected or accounted for
+ }
+ connected++;
+ break;
+ default:
+ break;
+ }
+ }
+ return (connected < max_connected_peers_);
+}
+
+bool BtifAvSource::DeletePeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it == peers_.end()) return false;
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ return true;
+}
+
+void BtifAvSource::DeleteIdlePeers() {
+ for (auto it = peers_.begin(); it != peers_.end();) {
+ BtifAvPeer* peer = it->second;
+ auto prev_it = it++;
+ if (!peer->CanBeDeleted()) continue;
+ BTIF_TRACE_WARNING("%s: Deleting idle peer: %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+ peer->Cleanup();
+ peers_.erase(prev_it);
+ delete peer;
+ }
+}
+
+void BtifAvSource::CleanupAllPeers() {
+ while (!peers_.empty()) {
+ auto it = peers_.begin();
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ }
+}
+
+void BtifAvSource::RegisterAllBtaHandles() {
+ for (int peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ BTA_AvRegister(BTA_AV_CHNL_AUDIO, kBtifAvSourceServiceName.c_str(), peer_id,
+ nullptr, UUID_SERVCLASS_AUDIO_SOURCE);
+ }
+}
+
+void BtifAvSource::DeregisterAllBtaHandles() {
+ for (auto it : peer_id2bta_handle_) {
+ tBTA_AV_HNDL bta_handle = it.second;
+ BTA_AvDeregister(bta_handle);
+ }
+ peer_id2bta_handle_.clear();
+}
+
+void BtifAvSource::BtaHandleRegistered(uint8_t peer_id,
+ tBTA_AV_HNDL bta_handle) {
+ peer_id2bta_handle_.insert(std::make_pair(peer_id, bta_handle));
+
+ // Set the BTA Handle for the Peer (if exists)
+ BtifAvPeer* peer = FindPeerByPeerId(peer_id);
+ if (peer != nullptr) {
+ peer->SetBtaHandle(bta_handle);
+ }
+}
+
+BtifAvSink::~BtifAvSink() { CleanupAllPeers(); }
+
+bt_status_t BtifAvSink::Init(btav_sink_callbacks_t* callbacks) {
+ if (enabled_) return BT_STATUS_SUCCESS;
+
+ CleanupAllPeers();
+ max_connected_peers_ =
+ osi_property_get_int32(kBtifAvMaxConnectedAudioDevices.c_str(),
+ kDefaultMaxConnectedAudioDevices);
+ callbacks_ = callbacks;
+
+ if (!btif_a2dp_sink_startup()) {
+ return BT_STATUS_FAIL; // Already running
+ }
+ btif_enable_service(BTA_A2DP_SINK_SERVICE_ID);
+ enabled_ = true;
+ return BT_STATUS_SUCCESS;
+}
+
+void BtifAvSink::Cleanup() {
+ if (!enabled_) return;
+
+ btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK);
+ do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_shutdown));
+
+ btif_disable_service(BTA_A2DP_SINK_SERVICE_ID);
+ CleanupAllPeers();
+
+ callbacks_ = nullptr;
+ enabled_ = false;
+}
+
+BtifAvPeer* BtifAvSink::FindPeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it != peers_.end()) return it->second;
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSink::FindPeerByHandle(tBTA_AV_HNDL bta_handle) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->BtaHandle() == bta_handle) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSink::FindPeerByPeerId(uint8_t peer_id) {
+ for (auto it : peers_) {
+ BtifAvPeer* peer = it.second;
+ if (peer->PeerId() == peer_id) {
+ return peer;
+ }
+ }
+ return nullptr;
+}
+
+BtifAvPeer* BtifAvSink::FindOrCreatePeer(const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle) {
+ BtifAvPeer* peer = FindPeer(peer_address);
+ if (peer != nullptr) return peer;
+
+ // Find next availabie Peer ID to use
+ uint8_t peer_id;
+ for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ if (FindPeerByPeerId(peer_id) == nullptr) break;
+ }
+ if (peer_id == kPeerIdMax) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot create peer for peer_address=%s : "
+ "cannot allocate unique Peer ID",
+ __PRETTY_FUNCTION__, peer_address.ToString().c_str());
+ return nullptr;
+ }
+
+ // Get the BTA Handle (if known)
+ if (bta_handle == kBtaHandleUnknown) {
+ auto it = peer_id2bta_handle_.find(peer_id);
+ if (it != peer_id2bta_handle_.end()) {
+ bta_handle = it->second;
+ }
+ }
+
+ peer = new BtifAvPeer(peer_address, AVDT_TSEP_SRC, bta_handle, peer_id);
+ peers_.insert(std::make_pair(peer_address, peer));
+ peer->Init();
+ return peer;
+}
+
+bool BtifAvSink::AllowedToConnect(const RawAddress& peer_address) const {
+ int connected = 0;
+
+ // Count peers that are in the process of connecting or already connected
+ for (auto it : peers_) {
+ const BtifAvPeer* peer = it.second;
+ switch (peer->StateMachine().StateId()) {
+ case BtifAvStateMachine::kStateOpening:
+ case BtifAvStateMachine::kStateOpened:
+ case BtifAvStateMachine::kStateStarted:
+ if (peer->PeerAddress() == peer_address) {
+ return true; // Already connected or accounted for
+ }
+ connected++;
+ break;
+ default:
+ break;
+ }
+ }
+ return (connected < max_connected_peers_);
+}
+
+bool BtifAvSink::DeletePeer(const RawAddress& peer_address) {
+ auto it = peers_.find(peer_address);
+ if (it == peers_.end()) return false;
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ return true;
+}
+
+void BtifAvSink::DeleteIdlePeers() {
+ for (auto it = peers_.begin(); it != peers_.end();) {
+ BtifAvPeer* peer = it->second;
+ auto prev_it = it++;
+ if (!peer->CanBeDeleted()) continue;
+ BTIF_TRACE_WARNING("%s: Deleting idle peer: %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+ peer->Cleanup();
+ peers_.erase(prev_it);
+ delete peer;
+ }
+}
+
+void BtifAvSink::CleanupAllPeers() {
+ while (!peers_.empty()) {
+ auto it = peers_.begin();
+ BtifAvPeer* peer = it->second;
+ peer->Cleanup();
+ peers_.erase(it);
+ delete peer;
+ }
+}
+
+void BtifAvSink::RegisterAllBtaHandles() {
+ for (int peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
+ BTA_AvRegister(BTA_AV_CHNL_AUDIO, kBtifAvSinkServiceName.c_str(), peer_id,
+ bta_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);
+ }
+}
+
+void BtifAvSink::DeregisterAllBtaHandles() {
+ for (auto it : peer_id2bta_handle_) {
+ tBTA_AV_HNDL bta_handle = it.second;
+ BTA_AvDeregister(bta_handle);
+ }
+ peer_id2bta_handle_.clear();
+}
+
+void BtifAvSink::BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle) {
+ peer_id2bta_handle_.insert(std::make_pair(peer_id, bta_handle));
+
+ // Set the BTA Handle for the Peer (if exists)
+ BtifAvPeer* peer = FindPeerByPeerId(peer_id);
+ if (peer != nullptr) {
+ peer->SetBtaHandle(bta_handle);
+ }
+}
+
+void BtifAvStateMachine::StateIdle::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ peer_.SetEdr(0);
+ peer_.ClearAllFlags();
+
+ // Stop A2DP if this is the active peer
+ RawAddress active_peer = RawAddress::kEmpty;
+ if (peer_.IsSink()) {
+ active_peer = btif_av_source.ActivePeer();
+ } else if (peer_.IsSource()) {
+ active_peer = btif_av_sink.ActivePeer();
+ }
+ if (peer_.PeerAddress() == active_peer || active_peer.IsEmpty()) {
+ btif_a2dp_on_idle();
+ }
+
+ // Reset the active peer if this was the active peer and
+ // the Idle state was reentered
+ if (peer_.PeerAddress() == active_peer && !active_peer.IsEmpty() &&
+ peer_.CanBeDeleted()) {
+ if (peer_.IsSink()) {
+ btif_av_source.SetActivePeer(RawAddress::kEmpty);
+ } else if (peer_.IsSource()) {
+ btif_av_sink.SetActivePeer(RawAddress::kEmpty);
+ }
+ }
+
+ // Delete peers that are re-entering the Idle state
+ if (peer_.IsSink()) {
+ do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSource::DeleteIdlePeers,
+ base::Unretained(&btif_av_source)));
+ } else if (peer_.IsSource()) {
+ do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSink::DeleteIdlePeers,
+ base::Unretained(&btif_av_sink)));
+ }
+}
+
+void BtifAvStateMachine::StateIdle::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ switch (event) {
+ case BTA_AV_ENABLE_EVT:
+ break;
+
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ case BTIF_AV_ACL_DISCONNECTED:
+ // Ignore. Just re-enter Idle so the peer can be deleted
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ if (peer_.BtaHandle() != kBtaHandleUnknown) {
+ BTA_AvClose(peer_.BtaHandle());
+ if (peer_.IsSource()) {
+ BTA_AvCloseRc(peer_.BtaHandle());
+ }
+ }
+ // Re-enter Idle so the peer can be deleted
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTIF_AV_CONNECT_REQ_EVT:
+ case BTA_AV_PENDING_EVT: {
+ bool can_connect = true;
+ peer_.SetSelfInitiatedConnection(event == BTIF_AV_CONNECT_REQ_EVT);
+ // Check whether connection is allowed
+ if (peer_.IsSink()) {
+ can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+ } else if (peer_.IsSource()) {
+ can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+ }
+ if (!can_connect) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot connect to peer %s: too many connected "
+ "peers",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+ }
+ BTA_AvOpen(peer_.PeerAddress(), peer_.BtaHandle(), true,
+ BTA_SEC_AUTHENTICATE, peer_.LocalUuidServiceClass());
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpening);
+ } break;
+ case BTIF_AV_AVRCP_OPEN_EVT:
+ case BTA_AV_RC_OPEN_EVT: {
+ // IOP_FIX: Jabra 620 only does AVRCP Open without AV Open whenever it
+ // connects. So as per the AV WP, an AVRCP connection cannot exist
+ // without an AV connection. Therefore, we initiate an AV connection
+ // if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
+ // We initiate the AV connection after a small 3s timeout to avoid any
+ // collisions from the headsets, as some headsets initiate the AVRCP
+ // connection first and then immediately initiate the AV connection
+ //
+ // TODO: We may need to do this only on an AVRCP Play. FixMe
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s received without AV",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+
+ bool can_connect = true;
+ // Check whether connection is allowed
+ if (peer_.IsSink()) {
+ can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+ } else if (peer_.IsSource()) {
+ can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+ }
+ if (!can_connect) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot connect to peer %s: too many connected "
+ "peers",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ break;
+ }
+ if (btif_av_source.Enabled()) {
+ alarm_set_on_mloop(
+ peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
+ btif_av_source_initiate_av_open_timer_timeout, &peer_);
+ } else if (btif_av_sink.Enabled()) {
+ alarm_set_on_mloop(peer_.AvOpenOnRcTimer(),
+ BtifAvPeer::kTimeoutAvOpenOnRcMs,
+ btif_av_sink_initiate_av_open_timer_timeout, &peer_);
+ }
+ if (event == BTA_AV_RC_OPEN_EVT) {
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ }
+ } break;
+
+ case BTA_AV_RC_BROWSE_OPEN_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ // In case Signalling channel is not down and remote started Streaming
+ // Procedure, we have to handle Config and Open event in Idle state.
+ // We hit these scenarios while running PTS test case for AVRCP Controller.
+ case BTIF_AV_SINK_CONFIG_REQ_EVT: {
+ btif_av_sink_config_req_t req;
+ // Copy to avoid alignment problems
+ memcpy(&req, p_data, sizeof(req));
+
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s sample_rate=%d channel_count=%d",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), req.sample_rate,
+ req.channel_count);
+ if (btif_av_sink.Enabled()) {
+ HAL_CBACK(btif_av_sink.Callbacks(), audio_config_cb, req.peer_bd,
+ req.sample_rate, req.channel_count);
+ }
+ } break;
+
+ case BTA_AV_OPEN_EVT: {
+ tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
+ btav_connection_state_t state;
+ int av_state;
+ tBTA_AV_STATUS status = p_bta_data->open.status;
+ bool can_connect = true;
+
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s flags=%s status=%d(%s) edr=0x%x",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), peer_.FlagsToString().c_str(),
+ status, (status == BTA_AV_SUCCESS) ? "SUCCESS" : "FAILED",
+ p_bta_data->open.edr);
+
+ if (p_bta_data->open.status == BTA_AV_SUCCESS) {
+ state = BTAV_CONNECTION_STATE_CONNECTED;
+ av_state = BtifAvStateMachine::kStateOpened;
+ peer_.SetEdr(p_bta_data->open.edr);
+ CHECK(peer_.PeerSep() == p_bta_data->open.sep);
+ // Check whether connection is allowed
+ if (peer_.IsSink()) {
+ can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+ } else if (peer_.IsSource()) {
+ can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+ if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+ }
+ } else {
+ state = BTAV_CONNECTION_STATE_DISCONNECTED;
+ av_state = BtifAvStateMachine::kStateIdle;
+ }
+
+ if (!can_connect) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot connect to peer %s: too many connected "
+ "peers",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ } else {
+ // Report the connection state to the application
+ btif_report_connection_state(peer_.PeerAddress(), state);
+ // Change state to Open/Idle based on the status
+ peer_.StateMachine().TransitionTo(av_state);
+ if (peer_.IsSink()) {
+ // If queued PLAY command, send it now
+ btif_rc_check_handle_pending_play(
+ p_bta_data->open.bd_addr,
+ (p_bta_data->open.status == BTA_AV_SUCCESS));
+ } else if (peer_.IsSource() &&
+ (p_bta_data->open.status == BTA_AV_SUCCESS)) {
+ // Bring up AVRCP connection as well
+ BTA_AvOpenRc(peer_.BtaHandle());
+ }
+ }
+ btif_queue_advance();
+ } break;
+
+ case BTA_AV_REMOTE_CMD_EVT:
+ case BTA_AV_VENDOR_CMD_EVT:
+ case BTA_AV_META_MSG_EVT:
+ case BTA_AV_RC_FEAT_EVT:
+ case BTA_AV_REMOTE_RSP_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ case BTIF_AV_AVRCP_CLOSE_EVT:
+ case BTA_AV_RC_CLOSE_EVT: {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s : Stopping AV timer",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ alarm_cancel(peer_.AvOpenOnRcTimer());
+
+ if (event == BTA_AV_RC_CLOSE_EVT) {
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ }
+ } break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(BTA_AV_FAIL);
+ break;
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+
+ return true;
+}
+
+void BtifAvStateMachine::StateOpening::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ // Inform the application that we are entering connecting state
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_CONNECTING);
+}
+
+void BtifAvStateMachine::StateOpening::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event,
+ void* p_data) {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ switch (event) {
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ break; // Ignore
+
+ case BTIF_AV_ACL_DISCONNECTED:
+ // ACL Disconnected needs to be handled only in Opening state, because
+ // it is in an intermediate state. In other states we can handle
+ // incoming/outgoing connect/disconnect requests.
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s: transitioning to Idle due to ACL Disconnect",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+ case BTA_AV_REJECT_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+
+ case BTA_AV_OPEN_EVT: {
+ tBTA_AV* p_bta_data = (tBTA_AV*)p_data;
+ btav_connection_state_t state;
+ int av_state;
+ tBTA_AV_STATUS status = p_bta_data->open.status;
+
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s flags=%s status=%d(%s) edr=0x%x",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), peer_.FlagsToString().c_str(),
+ status, (status == BTA_AV_SUCCESS) ? "SUCCESS" : "FAILED",
+ p_bta_data->open.edr);
+
+ if (p_bta_data->open.status == BTA_AV_SUCCESS) {
+ state = BTAV_CONNECTION_STATE_CONNECTED;
+ av_state = BtifAvStateMachine::kStateOpened;
+ peer_.SetEdr(p_bta_data->open.edr);
+ CHECK(peer_.PeerSep() == p_bta_data->open.sep);
+ } else {
+ if (btif_rc_is_connected_peer(peer_.PeerAddress())) {
+ // Disconnect the AVRCP connection, in case the A2DP connectiton
+ // failed for any reason.
+ BTIF_TRACE_WARNING("%s: Peer %s : Disconnecting AVRCP",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ uint8_t peer_handle =
+ btif_rc_get_connected_peer_handle(peer_.PeerAddress());
+ if (peer_handle != BTRC_HANDLE_NONE) {
+ BTA_AvCloseRc(peer_handle);
+ }
+ }
+ state = BTAV_CONNECTION_STATE_DISCONNECTED;
+ av_state = BtifAvStateMachine::kStateIdle;
+ }
+
+ // Report the connection state to the application
+ btif_report_connection_state(peer_.PeerAddress(), state);
+ // Change state to Open/Idle based on the status
+ peer_.StateMachine().TransitionTo(av_state);
+ if (peer_.IsSink()) {
+ // If queued PLAY command, send it now
+ btif_rc_check_handle_pending_play(
+ p_bta_data->open.bd_addr,
+ (p_bta_data->open.status == BTA_AV_SUCCESS));
+ } else if (peer_.IsSource() &&
+ (p_bta_data->open.status == BTA_AV_SUCCESS)) {
+ // Bring up AVRCP connection as well
+ BTA_AvOpenRc(peer_.BtaHandle());
+ }
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ } break;
+
+ case BTIF_AV_SINK_CONFIG_REQ_EVT: {
+ btif_av_sink_config_req_t req;
+ // Copy to avoid alignment problems
+ memcpy(&req, p_data, sizeof(req));
+
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s sample_rate=%d channel_count=%d",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), req.sample_rate,
+ req.channel_count);
+ if (peer_.IsSource() && btif_av_sink.Enabled()) {
+ HAL_CBACK(btif_av_sink.Callbacks(), audio_config_cb,
+ peer_.PeerAddress(), req.sample_rate, req.channel_count);
+ }
+ } break;
+
+ case BTIF_AV_CONNECT_REQ_EVT: {
+ // The device has moved already to Opening, hence don't report the
+ // connection state.
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s : device is already connecting, "
+ "ignore Connect request",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_queue_advance();
+ } break;
+
+ case BTA_AV_PENDING_EVT: {
+ // The device has moved already to Opening, hence don't report the
+ // connection state.
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s : device is already connecting, "
+ "ignore incoming request",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ } break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(BTA_AV_FAIL);
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ btif_a2dp_on_stopped(nullptr);
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+ BTA_AvClose(peer_.BtaHandle());
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ if (peer_.SelfInitiatedConnection()) {
+ btif_queue_advance();
+ }
+ break;
+
+ CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+ return true;
+}
+
+void BtifAvStateMachine::StateOpened::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart |
+ BtifAvPeer::kFlagPendingStop);
+
+ // Set the active peer if the first connected device
+ if (peer_.IsSink() && btif_av_source.ActivePeer().IsEmpty()) {
+ if (!btif_av_source.SetActivePeer(peer_.PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
+ peer_.PeerAddress().ToString().c_str());
+ }
+ }
+ if (peer_.IsSource() && btif_av_sink.ActivePeer().IsEmpty()) {
+ if (!btif_av_sink.SetActivePeer(peer_.PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
+ peer_.PeerAddress().ToString().c_str());
+ }
+ }
+}
+
+void BtifAvStateMachine::StateOpened::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
+}
+
+bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event,
+ void* p_data) {
+ tBTA_AV* p_av = (tBTA_AV*)p_data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ if ((event == BTA_AV_REMOTE_CMD_EVT) &&
+ peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend) &&
+ (p_av->remote_cmd.rc_id == AVRC_ID_PLAY)) {
+ BTIF_TRACE_EVENT("%s: Peer %s : Resetting remote suspend flag on RC PLAY",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+ }
+
+ switch (event) {
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ case BTIF_AV_ACL_DISCONNECTED:
+ break; // Ignore
+
+ case BTIF_AV_START_STREAM_REQ_EVT:
+ if (peer_.IsSink()) {
+ btif_a2dp_source_setup_codec(peer_.PeerAddress());
+ }
+ BTA_AvStart(peer_.BtaHandle());
+ peer_.SetFlags(BtifAvPeer::kFlagPendingStart);
+ break;
+
+ case BTA_AV_START_EVT: {
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s status=%d suspending=%d "
+ "initiator=%d flags=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), p_av->start.status,
+ p_av->start.suspending, p_av->start.initiator,
+ peer_.FlagsToString().c_str());
+
+ if ((p_av->start.status == BTA_SUCCESS) && p_av->start.suspending)
+ return true;
+
+ // If remote tries to start A2DP when DUT is A2DP Source, then Suspend.
+ // If A2DP is Sink and call is active, then disconnect the AVDTP channel.
+ if (peer_.IsSink() && !peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ BTIF_TRACE_WARNING("%s: Peer %s : trigger Suspend as remote initiated",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+ btif_av_source_dispatch_sm_event(peer_.PeerAddress(),
+ BTIF_AV_SUSPEND_STREAM_REQ_EVT);
+ }
+
+ // If peer is A2DP Source, we do not want to ACK commands on UIPC
+ if (peer_.IsSink() &&
+ btif_a2dp_on_started(
+ peer_.PeerAddress(), &p_av->start,
+ peer_.CheckFlags(BtifAvPeer::kFlagPendingStart))) {
+ // Only clear pending flag after acknowledgement
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
+ }
+
+ // Remain in Open state if status failed
+ if (p_av->start.status != BTA_AV_SUCCESS) return false;
+
+ if (peer_.IsSource()) {
+ // Remove flush state, ready for streaming
+ btif_a2dp_sink_set_rx_flush(false);
+ }
+
+ // Change state to Started, send acknowledgement if start is pending
+ if (peer_.IsSink() && peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ btif_a2dp_on_started(peer_.PeerAddress(), nullptr, true);
+ // Pending start flag will be cleared when exit current state
+ }
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateStarted);
+
+ } break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ BTA_AvClose(peer_.BtaHandle());
+ if (peer_.IsSource()) {
+ BTA_AvCloseRc(peer_.BtaHandle());
+ }
+
+ // Inform the application that we are disconnecting
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTING);
+
+ // Wait in closing state until fully closed
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateClosing);
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ // AVDTP link is closed
+ btif_a2dp_on_stopped(nullptr);
+
+ // Inform the application that we are disconnected
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+
+ // Change state to Idle, send acknowledgement if start is pending
+ if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+ // Pending start flag will be cleared when exit current state
+ }
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTA_AV_RECONFIG_EVT:
+ if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart) &&
+ (p_av->reconfig.status == BTA_AV_SUCCESS)) {
+ BTIF_TRACE_WARNING(
+ "%s : Peer %s : Reconfig done - calling BTA_AvStart()",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ BTA_AvStart(peer_.BtaHandle());
+ } else if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
+ peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
+ btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+ }
+ break;
+
+ case BTIF_AV_CONNECT_REQ_EVT: {
+ BTIF_TRACE_WARNING("%s: Peer %s : Ignore %s for same device",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_queue_advance();
+ } break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(BTA_AV_FAIL);
+ break;
+
+ case BTIF_AV_AVRCP_REMOTE_PLAY_EVT:
+ if (peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend)) {
+ BTIF_TRACE_EVENT(
+ "%s: Peer %s : Resetting remote suspend flag on RC PLAY",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+ }
+ break;
+
+ CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+ return true;
+}
+
+void BtifAvStateMachine::StateStarted::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ // We are again in started state, clear any remote suspend flags
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+
+ // Report that we have entered the Streaming stage. Usually, this should
+ // be followed by focus grant. See update_audio_focus_state()
+ btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STARTED);
+}
+
+void BtifAvStateMachine::StateStarted::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event,
+ void* p_data) {
+ tBTA_AV* p_av = (tBTA_AV*)p_data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ switch (event) {
+ case BTIF_AV_ACL_DISCONNECTED:
+ break; // Ignore
+
+ case BTIF_AV_START_STREAM_REQ_EVT:
+ // We were remotely started, just ACK back the local request
+ if (peer_.IsSink())
+ btif_a2dp_on_started(peer_.PeerAddress(), nullptr, true);
+ break;
+
+ // FIXME -- use suspend = true always to work around issue with BTA AV
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+ // Set pending flag to ensure the BTIF task is not trying to restart
+ // the stream while suspend is in progress.
+ peer_.SetFlags(BtifAvPeer::kFlagLocalSuspendPending);
+
+ // If we were remotely suspended but suspend locally, local suspend
+ // always overrides.
+ peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+
+ if (peer_.IsSink()) {
+ // Immediately stop transmission of frames while suspend is pending
+ btif_a2dp_source_set_tx_flush(true);
+ } else if (peer_.IsSource()) {
+ btif_a2dp_on_stopped(nullptr);
+ }
+ BTA_AvStop(peer_.BtaHandle(), true);
+ break;
+
+ case BTIF_AV_DISCONNECT_REQ_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ // Request AVDTP to close
+ BTA_AvClose(peer_.BtaHandle());
+ if (peer_.IsSource()) {
+ BTA_AvCloseRc(peer_.BtaHandle());
+ }
+
+ // Inform the application that we are disconnecting
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTING);
+
+ // Wait in closing state until fully closed
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateClosing);
+ break;
+
+ case BTA_AV_SUSPEND_EVT:
+ BTIF_TRACE_WARNING(
+ "%s: Peer %s : event=%s status=%d initiator=%d flags=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(), p_av->suspend.status,
+ p_av->suspend.initiator, peer_.FlagsToString().c_str());
+
+ // A2DP suspended, stop A2DP encoder/decoder until resumed
+ btif_a2dp_on_suspended(&p_av->suspend);
+
+ // If not successful, remain in current state
+ if (p_av->suspend.status != BTA_AV_SUCCESS) {
+ peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending);
+
+ if (peer_.IsSink()) {
+ // Suspend failed, reset back tx flush state
+ btif_a2dp_source_set_tx_flush(false);
+ }
+ return false;
+ }
+
+ if (p_av->suspend.initiator != true) {
+ // Remote suspend, notify HAL and await audioflinger to
+ // suspend/stop stream.
+ //
+ // Set remote suspend flag to block media task from restarting
+ // stream only if we did not already initiate a local suspend.
+ if (!peer_.CheckFlags(BtifAvPeer::kFlagLocalSuspendPending))
+ peer_.SetFlags(BtifAvPeer::kFlagRemoteSuspend);
+
+ btif_report_audio_state(peer_.PeerAddress(),
+ BTAV_AUDIO_STATE_REMOTE_SUSPEND);
+ } else {
+ btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED);
+ }
+
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpened);
+
+ // Suspend completed and state changed, clear pending status
+ peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending);
+ break;
+
+ case BTA_AV_STOP_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ peer_.SetFlags(BtifAvPeer::kFlagPendingStop);
+ btif_a2dp_on_stopped(&p_av->suspend);
+
+ btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED);
+
+ // If stop was successful, change state to Open
+ if (p_av->suspend.status == BTA_AV_SUCCESS)
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpened);
+
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ peer_.SetFlags(BtifAvPeer::kFlagPendingStop);
+
+ // AVDTP link is closed
+ btif_a2dp_on_stopped(nullptr);
+
+ // Inform the application that we are disconnected
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTA_AvOffloadStart(peer_.BtaHandle());
+ break;
+
+ case BTA_AV_OFFLOAD_START_RSP_EVT:
+ btif_a2dp_on_offload_started(p_av->status);
+ break;
+
+ CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+
+ return true;
+}
+
+void BtifAvStateMachine::StateClosing::OnEnter() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+
+ if (peer_.IsSink()) {
+ // Immediately stop transmission of frames
+ btif_a2dp_source_set_tx_flush(true);
+ // Wait for Audio Flinger to stop A2DP
+ } else if (peer_.IsSource()) {
+ btif_a2dp_sink_set_rx_flush(true);
+ }
+}
+
+void BtifAvStateMachine::StateClosing::OnExit() {
+ BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str());
+}
+
+bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event,
+ void* p_data) {
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str());
+
+ switch (event) {
+ case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+ case BTIF_AV_ACL_DISCONNECTED:
+ break; // Ignore
+
+ case BTA_AV_STOP_EVT:
+ case BTIF_AV_STOP_STREAM_REQ_EVT:
+ btif_a2dp_on_stopped(nullptr);
+ break;
+
+ case BTA_AV_CLOSE_EVT:
+ // Inform the application that we are disconnecting
+ btif_report_connection_state(peer_.PeerAddress(),
+ BTAV_CONNECTION_STATE_DISCONNECTED);
+
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
+ // Handle the RC_CLOSE event for the cleanup
+ case BTA_AV_RC_CLOSE_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ // Handle the RC_BROWSE_CLOSE event for testing
+ case BTA_AV_RC_BROWSE_CLOSE_EVT:
+ btif_rc_handler(event, (tBTA_AV*)p_data);
+ break;
+
+ case BTIF_AV_OFFLOAD_START_REQ_EVT:
+ BTIF_TRACE_ERROR("%s: Peer %s : event=%s: stream is not Opened",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_a2dp_on_offload_started(BTA_AV_FAIL);
+ break;
+
+ default:
+ BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Timer to trigger AV Open on the Source if the remote Sink device establishes
+ * AVRCP connection without AV connection. The timer is needed to interoperate
+ * with headsets that do establish AV after AVRCP connection.
+ */
+static void btif_av_source_initiate_av_open_timer_timeout(void* data) {
+ BtifAvPeer* peer = (BtifAvPeer*)data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+
+ // Check if AVRCP is connected to the peer
+ if (!btif_rc_is_connected_peer(peer->PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: AVRCP peer %s is not connected", __func__,
+ peer->PeerAddress().ToString().c_str());
+ return;
+ }
+
+ // Connect to the AVRCP peer
+ if (btif_av_source.Enabled() &&
+ btif_av_source.FindPeer(peer->PeerAddress()) == peer) {
+ BTIF_TRACE_DEBUG("%s: Connecting to AVRCP peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+ btif_av_source_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_CONNECT_REQ_EVT);
+ }
+}
+
+/**
+ * Timer to trigger AV Open on the Sink if the remote Source device establishes
+ * AVRCP connection without AV connection.
+ */
+static void btif_av_sink_initiate_av_open_timer_timeout(void* data) {
+ BtifAvPeer* peer = (BtifAvPeer*)data;
+
+ BTIF_TRACE_DEBUG("%s: Peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+
+ // Check if AVRCP is connected to the peer
+ if (!btif_rc_is_connected_peer(peer->PeerAddress())) {
+ BTIF_TRACE_ERROR("%s: AVRCP peer %s is not connected", __func__,
+ peer->PeerAddress().ToString().c_str());
+ return;
+ }
+
+ // Connect to the AVRCP peer
+ if (btif_av_sink.Enabled() &&
+ btif_av_sink.FindPeer(peer->PeerAddress()) == peer) {
+ BTIF_TRACE_DEBUG("%s: Connecting to AVRCP peer %s", __func__,
+ peer->PeerAddress().ToString().c_str());
+ btif_av_sink_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_CONNECT_REQ_EVT);
+ }
+}
+
+/**
+ * Report the A2DP connection state
+ *
+ * @param peer_address the peer address
+ * @param state the connection state
+ */
+static void btif_report_connection_state(const RawAddress& peer_address,
+ btav_connection_state_t state) {
+ BTIF_TRACE_WARNING("%s: peer_address=%s state=%d", __func__,
+ peer_address.ToString().c_str(), state);
+
+ if (btif_av_source.Enabled()) {
+ HAL_CBACK(btif_av_source.Callbacks(), connection_state_cb, peer_address,
+ state);
+ } else if (btif_av_sink.Enabled()) {
+ HAL_CBACK(btif_av_sink.Callbacks(), connection_state_cb, peer_address,
+ state);
+ }
+}
+
+/**
+ * Report the audio state of the A2DP connection.
+ * The state is updated when either the remote ends starts streaming
+ * (Started state) or whenever it transitions out of Started state
+ * (to Opened or Streaming state).
+ *
+ * @param peer_address the peer address
+ * @param state the audio state
+ */
+static void btif_report_audio_state(const RawAddress& peer_address,
+ btav_audio_state_t state) {
+ BTIF_TRACE_WARNING("%s: peer_address=%s state=%d", __func__,
+ peer_address.ToString().c_str(), state);
+
+ if (btif_av_source.Enabled()) {
+ HAL_CBACK(btif_av_source.Callbacks(), audio_state_cb, peer_address, state);
+ } else if (btif_av_sink.Enabled()) {
+ HAL_CBACK(btif_av_sink.Callbacks(), audio_state_cb, peer_address, state);
+ }
+}
+
+void btif_av_report_source_codec_state(
+ const RawAddress& peer_address,
+ const btav_a2dp_codec_config_t& codec_config,
+ const std::vector<btav_a2dp_codec_config_t>& codecs_local_capabilities,
+ const std::vector<btav_a2dp_codec_config_t>&
+ codecs_selectable_capabilities) {
+ BTIF_TRACE_EVENT("%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ if (btif_av_source.Enabled()) {
+ HAL_CBACK(btif_av_source.Callbacks(), audio_config_cb, peer_address,
+ codec_config, codecs_local_capabilities,
+ codecs_selectable_capabilities);
+ }
+}
+
+/**
+ * Process BTIF or BTA AV or BTA AVRCP events. The processing is done on the
+ * JNI thread.
+ *
+ * @param peer_sep the corresponding peer's SEP: AVDT_TSEP_SRC if the peer
+ * is A2DP Source, or AVDT_TSEP_SNK if the peer is A2DP Sink.
+ * @param peer_address the peer address if known, otherwise RawAddress::kEmpty
+ * @param bta_handle the BTA handle for the peer if known, otherwise
+ * kBtaHandleUnknown
+ * @param btif_av_event the corresponding event
+ */
+static void btif_av_handle_event(uint8_t peer_sep,
+ const RawAddress& peer_address,
+ tBTA_AV_HNDL bta_handle,
+ const BtifAvEvent& btif_av_event) {
+ BtifAvPeer* peer = nullptr;
+ BTIF_TRACE_EVENT("%s: peer_sep=%s (%d) peer_address=%s handle=%d event=%s",
+ __func__, (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
+ peer_sep, peer_address.ToString().c_str(), bta_handle,
+ btif_av_event.ToString().c_str());
+
+ // Find the peer
+ if (peer_address != RawAddress::kEmpty) {
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
+ }
+ } else if (bta_handle != kBtaHandleUnknown) {
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer = btif_av_source.FindPeerByHandle(bta_handle);
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ peer = btif_av_sink.FindPeerByHandle(bta_handle);
+ }
+ }
+ if (peer == nullptr) {
+ BTIF_TRACE_ERROR(
+ "%s: Cannot find or create %s peer for peer_address=%s handle=%d : "
+ "event dropped: %s",
+ __func__, (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
+ peer_address.ToString().c_str(), bta_handle,
+ btif_av_event.ToString().c_str());
+ return;
+ }
+
+ peer->StateMachine().ProcessEvent(btif_av_event.Event(),
+ btif_av_event.Data());
+}
+
+/**
+ * Process BTA AV or BTA AVRCP events. The processing is done on the JNI
+ * thread.
+ *
+ * @param peer_sep the corresponding peer's SEP: AVDT_TSEP_SRC if the peer
+ * is A2DP Source, or AVDT_TSEP_SNK if the peer is A2DP Sink.
+ * @param btif_av_event the corresponding event
+ */
+static void btif_av_handle_bta_av_event(uint8_t peer_sep,
+ const BtifAvEvent& btif_av_event) {
+ RawAddress peer_address = RawAddress::kEmpty;
+ tBTA_AV_HNDL bta_handle = kBtaHandleUnknown;
+ tBTA_AV_EVT event = btif_av_event.Event();
+ tBTA_AV* p_data = (tBTA_AV*)btif_av_event.Data();
+
+ BTIF_TRACE_DEBUG("%s: peer_sep=%s (%d) event=%s", __func__,
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep,
+ btif_av_event.ToString().c_str());
+
+ switch (event) {
+ case BTA_AV_ENABLE_EVT: {
+ const tBTA_AV_ENABLE& enable = p_data->enable;
+ BTIF_TRACE_DEBUG("%s: features=0x%x", __func__, enable.features);
+ return; // Nothing to do
+ }
+ case BTA_AV_REGISTER_EVT: {
+ const tBTA_AV_REGISTER& registr = p_data->registr;
+ bta_handle = registr.hndl;
+ uint8_t peer_id = registr.app_id; // The PeerId is used as AppId
+ BTIF_TRACE_DEBUG("%s: handle=%d app_id=%d", __func__, bta_handle,
+ registr.app_id);
+ if (peer_sep == AVDT_TSEP_SNK) {
+ btif_av_source.BtaHandleRegistered(peer_id, bta_handle);
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ btif_av_sink.BtaHandleRegistered(peer_id, bta_handle);
+ }
+ return; // Nothing else to do
+ }
+ case BTA_AV_OPEN_EVT: {
+ const tBTA_AV_OPEN& open = p_data->open;
+ peer_address = open.bd_addr;
+ bta_handle = open.hndl;
+ break;
+ }
+ case BTA_AV_CLOSE_EVT: {
+ const tBTA_AV_CLOSE& close = p_data->close;
+ bta_handle = close.hndl;
+ break;
+ }
+ case BTA_AV_START_EVT: {
+ const tBTA_AV_START& start = p_data->start;
+ bta_handle = start.hndl;
+ break;
+ }
+ case BTA_AV_SUSPEND_EVT:
+ case BTA_AV_STOP_EVT: {
+ const tBTA_AV_SUSPEND& suspend = p_data->suspend;
+ bta_handle = suspend.hndl;
+ break;
+ }
+ case BTA_AV_PROTECT_REQ_EVT: {
+ const tBTA_AV_PROTECT_REQ& protect_req = p_data->protect_req;
+ bta_handle = protect_req.hndl;
+ break;
+ }
+ case BTA_AV_PROTECT_RSP_EVT: {
+ const tBTA_AV_PROTECT_RSP& protect_rsp = p_data->protect_rsp;
+ bta_handle = protect_rsp.hndl;
+ break;
+ }
+ case BTA_AV_RC_OPEN_EVT: {
+ const tBTA_AV_RC_OPEN& rc_open = p_data->rc_open;
+ peer_address = rc_open.peer_addr;
+ break;
+ }
+ case BTA_AV_RC_CLOSE_EVT: {
+ const tBTA_AV_RC_CLOSE& rc_close = p_data->rc_close;
+ peer_address = rc_close.peer_addr;
+ break;
+ }
+ case BTA_AV_RC_BROWSE_OPEN_EVT: {
+ const tBTA_AV_RC_BROWSE_OPEN& rc_browse_open = p_data->rc_browse_open;
+ peer_address = rc_browse_open.peer_addr;
+ break;
+ }
+ case BTA_AV_RC_BROWSE_CLOSE_EVT: {
+ const tBTA_AV_RC_BROWSE_CLOSE& rc_browse_close = p_data->rc_browse_close;
+ peer_address = rc_browse_close.peer_addr;
+ break;
+ }
+ case BTA_AV_REMOTE_CMD_EVT:
+ case BTA_AV_REMOTE_RSP_EVT:
+ case BTA_AV_VENDOR_CMD_EVT:
+ case BTA_AV_VENDOR_RSP_EVT:
+ case BTA_AV_META_MSG_EVT:
+ case BTA_AV_OFFLOAD_START_RSP_EVT: {
+ // TODO: Might be wrong - this code will be removed once those
+ // events are received from the AVRCP module.
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer_address = btif_av_source.ActivePeer();
+ } else if (peer_sep == AVDT_TSEP_SRC) {
+ peer_address = btif_av_sink.ActivePeer();
+ }
+ break;
+ }
+ case BTA_AV_RECONFIG_EVT: {
+ const tBTA_AV_RECONFIG& reconfig = p_data->reconfig;
+ bta_handle = reconfig.hndl;
+ break;
+ }
+ case BTA_AV_PENDING_EVT: {
+ const tBTA_AV_PEND& pend = p_data->pend;
+ peer_address = pend.bd_addr;
+ break;
+ }
+ case BTA_AV_REJECT_EVT: {
+ const tBTA_AV_REJECT& reject = p_data->reject;
+ peer_address = reject.bd_addr;
+ bta_handle = reject.hndl;
+ break;
+ }
+ case BTA_AV_RC_FEAT_EVT: {
+ const tBTA_AV_RC_FEAT& rc_feat = p_data->rc_feat;
+ peer_address = rc_feat.peer_addr;
+ break;
+ }
+ }
+ BTIF_TRACE_DEBUG("%s: peer_address=%s handle=%d", __func__,
+ peer_address.ToString().c_str(), bta_handle);
+
+ btif_av_handle_event(peer_sep, peer_address, bta_handle, btif_av_event);
+}
+
+static void bta_av_source_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
+ BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
+ BTIF_TRACE_EVENT("%s: event=%s", __func__, btif_av_event.ToString().c_str());
+
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_bta_av_event,
+ AVDT_TSEP_SNK /* peer_sep */, btif_av_event));
+}
+
+static void bta_av_sink_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
+ BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_bta_av_event,
+ AVDT_TSEP_SRC /* peer_sep */, btif_av_event));
+}
+
+// TODO: All processing should be done on the JNI thread
+static void bta_av_sink_media_callback(tBTA_AV_EVT event,
tBTA_AV_MEDIA* p_data) {
+ BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
+
switch (event) {
case BTA_AV_SINK_MEDIA_DATA_EVT: {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- if ((state == BTIF_AV_STATE_STARTED) || (state == BTIF_AV_STATE_OPENED)) {
- uint8_t queue_len = btif_a2dp_sink_enqueue_buf((BT_HDR*)p_data);
- BTIF_TRACE_DEBUG("%s: packets in sink queue %d", __func__, queue_len);
+ BtifAvPeer* peer = btif_av_sink_find_peer(btif_av_sink.ActivePeer());
+ if (peer != nullptr) {
+ int state = peer->StateMachine().StateId();
+ if ((state == BtifAvStateMachine::kStateStarted) ||
+ (state == BtifAvStateMachine::kStateOpened)) {
+ uint8_t queue_len = btif_a2dp_sink_enqueue_buf((BT_HDR*)p_data);
+ BTIF_TRACE_DEBUG("%s: Packets in Sink queue %d", __func__, queue_len);
+ }
}
break;
}
case BTA_AV_SINK_MEDIA_CFG_EVT: {
btif_av_sink_config_req_t config_req;
- /* send a command to BT Media Task */
+ // Update the codec info of the A2DP Sink decoder
btif_a2dp_sink_update_decoder((uint8_t*)(p_data->avk_config.codec_info));
- /* Switch to BTIF context */
+
config_req.sample_rate =
A2DP_GetTrackSampleRate(p_data->avk_config.codec_info);
if (config_req.sample_rate == -1) {
- APPL_TRACE_ERROR("%s: cannot get the track frequency", __func__);
+ APPL_TRACE_ERROR("%s: Cannot get the track frequency", __func__);
break;
}
config_req.channel_count =
A2DP_GetTrackChannelCount(p_data->avk_config.codec_info);
if (config_req.channel_count == -1) {
- APPL_TRACE_ERROR("%s: cannot get the channel count", __func__);
+ APPL_TRACE_ERROR("%s: Cannot get the channel count", __func__);
break;
}
-
config_req.peer_bd = p_data->avk_config.bd_addr;
- btif_transfer_context(btif_av_handle_event, BTIF_AV_SINK_CONFIG_REQ_EVT,
- (char*)&config_req, sizeof(config_req), NULL);
+ BtifAvEvent btif_av_event(BTIF_AV_SINK_CONFIG_REQ_EVT, &config_req,
+ sizeof(config_req));
+ do_in_jni_thread(FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SRC, // peer_sep
+ config_req.peer_bd,
+ kBtaHandleUnknown, btif_av_event));
break;
}
default:
@@ -1252,173 +2318,168 @@
}
}
-/*******************************************************************************
- *
- * Function btif_av_init
- *
- * Description Initializes btif AV if not already done
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
-bt_status_t btif_av_init(int service_id) {
- if (btif_av_cb.sm_handle == NULL) {
- alarm_free(av_open_on_rc_timer);
- av_open_on_rc_timer = alarm_new("btif_av.av_open_on_rc_timer");
-
- switch (service_id) {
- case BTA_A2DP_SOURCE_SERVICE_ID:
- if (!btif_a2dp_source_startup())
- return BT_STATUS_FAIL; // Already running
- break;
- case BTA_A2DP_SINK_SERVICE_ID:
- if (!btif_a2dp_sink_startup())
- return BT_STATUS_FAIL; // Already running
- break;
- default:
- break;
- }
-
- btif_enable_service(service_id);
-
- /* Also initialize the AV state machine */
- btif_av_cb.sm_handle = btif_sm_init(
- (const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
- }
-
- return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
- *
- * Function init_src
- *
- * Description Initializes the AV interface for source mode
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
+// Initializes the AV interface for source mode
static bt_status_t init_src(
btav_source_callbacks_t* callbacks,
std::vector<btav_a2dp_codec_config_t> codec_priorities) {
BTIF_TRACE_EVENT("%s", __func__);
-
- btif_av_cb.codec_priorities = codec_priorities;
- bt_status_t status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
- if (status == BT_STATUS_SUCCESS) bt_av_src_callbacks = callbacks;
-
- return status;
+ return btif_av_source.Init(callbacks, codec_priorities);
}
-/*******************************************************************************
- *
- * Function init_sink
- *
- * Description Initializes the AV interface for sink mode
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-
+// Initializes the AV interface for sink mode
static bt_status_t init_sink(btav_sink_callbacks_t* callbacks) {
BTIF_TRACE_EVENT("%s", __func__);
-
- bt_status_t status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);
- if (status == BT_STATUS_SUCCESS) bt_av_sink_callbacks = callbacks;
-
- return status;
+ return btif_av_sink.Init(callbacks);
}
-/*******************************************************************************
- *
- * Function update_audio_focus_state
- *
- * Description Updates the final focus state reported by components calling
- * this module.
- *
- * Returns None
- *
- ******************************************************************************/
+// Updates the final focus state reported by components calling this module
static void update_audio_focus_state(int state) {
BTIF_TRACE_DEBUG("%s: state=%d", __func__, state);
btif_a2dp_sink_set_focus_state_req((btif_a2dp_sink_focus_state_t)state);
}
-/*******************************************************************************
- *
- * Function update_audio_track_gain
- *
- * Description Updates the track gain (used for ducking).
- *
- * Returns None
- *
- ******************************************************************************/
+// Updates the track gain (used for ducking).
static void update_audio_track_gain(float gain) {
BTIF_TRACE_DEBUG("%s: gain=%f", __func__, gain);
btif_a2dp_sink_set_audio_track_gain(gain);
}
-/*******************************************************************************
- *
- * Function connect
- *
- * Description Establishes the AV signalling channel with the remote
- * headset
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
+// Establishes the AV signalling channel with the remote headset
+static bt_status_t connect_int(RawAddress* peer_address, uint16_t uuid) {
+ BTIF_TRACE_EVENT("%s: peer_address=%s uuid=0x%x", __func__,
+ peer_address->ToString().c_str(), uuid);
-static bt_status_t connect_int(RawAddress* bd_addr, uint16_t uuid) {
- btif_av_connect_req_t connect_req;
- connect_req.target_bda = bd_addr;
- connect_req.uuid = uuid;
- BTIF_TRACE_EVENT("%s", __func__);
-
- btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT,
- (char*)&connect_req);
-
+ BtifAvPeer* peer = nullptr;
+ if (uuid == UUID_SERVCLASS_AUDIO_SOURCE) {
+ peer = btif_av_source.FindOrCreatePeer(*peer_address, kBtaHandleUnknown);
+ if (peer == nullptr) {
+ return BT_STATUS_FAIL;
+ }
+ } else if (uuid == UUID_SERVCLASS_AUDIO_SINK) {
+ peer = btif_av_sink.FindOrCreatePeer(*peer_address, kBtaHandleUnknown);
+ if (peer == nullptr) {
+ return BT_STATUS_FAIL;
+ }
+ }
+ peer->StateMachine().ProcessEvent(BTIF_AV_CONNECT_REQ_EVT, nullptr);
return BT_STATUS_SUCCESS;
}
-static bt_status_t src_connect_sink(RawAddress* bd_addr) {
- BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
+// Set the active peer
+static void set_active_peer_int(uint8_t peer_sep,
+ const RawAddress& peer_address) {
+ BTIF_TRACE_EVENT("%s: peer_sep=%s (%d) peer_address=%s", __func__,
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep,
+ peer_address.ToString().c_str());
- return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);
+ BtifAvPeer* peer = nullptr;
+ if (peer_sep == AVDT_TSEP_SNK) {
+ peer = btif_av_source.FindPeer(peer_address);
+ if (peer != nullptr && peer->IsConnected()) {
+ if (!btif_av_source.SetActivePeer(peer_address)) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
+ peer_address.ToString().c_str());
+ }
+ return;
+ }
+ }
+ if (peer_sep == AVDT_TSEP_SRC) {
+ peer = btif_av_sink.FindPeer(peer_address);
+ if (peer != nullptr && peer->IsConnected()) {
+ if (!btif_av_sink.SetActivePeer(peer_address)) {
+ BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
+ peer_address.ToString().c_str());
+ }
+ return;
+ }
+ }
+ // If reached here, we could not set the active peer
+ BTIF_TRACE_ERROR("%s: Cannot set active %s peer to %s: peer not %s", __func__,
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
+ peer_address.ToString().c_str(),
+ (peer == nullptr) ? "found" : "connected");
}
-static bt_status_t sink_connect_src(RawAddress* bd_addr) {
- BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
+static bt_status_t src_connect_sink(const RawAddress& peer_address) {
+ BTIF_TRACE_EVENT("%s: Peer %s", __func__, peer_address.ToString().c_str());
- return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, bd_addr, connect_int);
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ RawAddress peer_address_copy(peer_address);
+ return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, &peer_address_copy,
+ connect_int);
}
-/*******************************************************************************
- *
- * Function disconnect
- *
- * Description Tears down the AV signalling channel with the remote headset
- *
- * Returns bt_status_t
- *
- ******************************************************************************/
-static bt_status_t disconnect(RawAddress* bd_addr) {
- BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
+static bt_status_t sink_connect_src(const RawAddress& peer_address) {
+ BTIF_TRACE_WARNING("%s: Peer %s", __func__, peer_address.ToString().c_str());
- /* Switch to BTIF context */
- return btif_transfer_context(btif_av_handle_event, BTIF_AV_DISCONNECT_REQ_EVT,
- (char*)bd_addr, sizeof(RawAddress), NULL);
+ if (!btif_av_sink.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Sink is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ RawAddress peer_address_copy(peer_address);
+ return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, &peer_address_copy,
+ connect_int);
+}
+
+static bt_status_t src_disconnect_sink(const RawAddress& peer_address) {
+ BTIF_TRACE_WARNING("%s: Peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address,
+ sizeof(peer_address));
+ return do_in_jni_thread(
+ FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SNK, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
+}
+
+static bt_status_t sink_disconnect_src(const RawAddress& peer_address) {
+ BTIF_TRACE_WARNING("%s: Peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!btif_av_sink.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Sink is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address,
+ sizeof(peer_address));
+ return do_in_jni_thread(
+ FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SRC, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
+}
+
+static bt_status_t src_set_active_sink(const RawAddress& peer_address) {
+ BTIF_TRACE_EVENT("%s: Peer %s", __func__, peer_address.ToString().c_str());
+
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
+
+ return do_in_jni_thread(FROM_HERE, base::Bind(&set_active_peer_int,
+ AVDT_TSEP_SNK, // peer_sep
+ peer_address));
}
static bt_status_t codec_config_src(
+ const RawAddress& peer_address,
std::vector<btav_a2dp_codec_config_t> codec_preferences) {
BTIF_TRACE_EVENT("%s", __func__);
- CHECK_BTAV_INIT();
+
+ if (!btif_av_source.Enabled()) {
+ BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+ return BT_STATUS_NOT_READY;
+ }
for (auto cp : codec_preferences) {
BTIF_TRACE_DEBUG(
@@ -1430,365 +2491,421 @@
__func__, cp.codec_type, cp.codec_priority, cp.sample_rate,
cp.bits_per_sample, cp.channel_mode, cp.codec_specific_1,
cp.codec_specific_2, cp.codec_specific_3, cp.codec_specific_4);
- btif_transfer_context(btif_av_handle_event, BTIF_AV_SOURCE_CONFIG_REQ_EVT,
- reinterpret_cast<char*>(&cp), sizeof(cp), NULL);
+ do_in_jni_thread(
+ FROM_HERE, base::Bind(&btif_a2dp_source_encoder_user_config_update_req,
+ peer_address, cp));
}
return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function cleanup
- *
- * Description Shuts down the AV interface and does the cleanup
- *
- * Returns None
- *
- ******************************************************************************/
-static void cleanup(int service_uuid) {
- BTIF_TRACE_EVENT("%s", __func__);
-
- btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT, NULL, 0,
- NULL);
-
- btif_disable_service(service_uuid);
-
- alarm_free(av_open_on_rc_timer);
- av_open_on_rc_timer = NULL;
-
- /* Also shut down the AV state machine */
- btif_sm_shutdown(btif_av_cb.sm_handle);
- btif_av_cb.sm_handle = NULL;
-}
-
static void cleanup_src(void) {
BTIF_TRACE_EVENT("%s", __func__);
-
- btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE);
- if (bt_av_src_callbacks) {
- bt_av_src_callbacks = NULL;
- if (bt_av_sink_callbacks == NULL) cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
- }
+ do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSource::Cleanup,
+ base::Unretained(&btif_av_source)));
}
static void cleanup_sink(void) {
BTIF_TRACE_EVENT("%s", __func__);
-
- btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK);
- if (bt_av_sink_callbacks) {
- bt_av_sink_callbacks = NULL;
- if (bt_av_src_callbacks == NULL) cleanup(BTA_A2DP_SINK_SERVICE_ID);
- }
+ do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSink::Cleanup,
+ base::Unretained(&btif_av_sink)));
}
static const btav_source_interface_t bt_av_src_interface = {
sizeof(btav_source_interface_t),
init_src,
src_connect_sink,
- disconnect,
+ src_disconnect_sink,
+ src_set_active_sink,
codec_config_src,
cleanup_src,
};
static const btav_sink_interface_t bt_av_sink_interface = {
- sizeof(btav_sink_interface_t),
- init_sink,
- sink_connect_src,
- disconnect,
- cleanup_sink,
- update_audio_focus_state,
+ sizeof(btav_sink_interface_t), init_sink, sink_connect_src,
+ sink_disconnect_src, cleanup_sink, update_audio_focus_state,
update_audio_track_gain,
};
-/*******************************************************************************
- *
- * Function btif_av_get_addr
- *
- * Description Fetches current AV BD address
- *
- * Returns BD address
- *
- ******************************************************************************/
-
-RawAddress btif_av_get_addr(void) { return btif_av_cb.peer_bda; }
-
-/*******************************************************************************
- * Function btif_av_is_sink_enabled
- *
- * Description Checks if A2DP Sink is enabled or not
- *
- * Returns true if A2DP Sink is enabled, false otherwise
- *
- ******************************************************************************/
-
-bool btif_av_is_sink_enabled(void) {
- return (bt_av_sink_callbacks != NULL) ? true : false;
+RawAddress btif_av_source_active_peer(void) {
+ return btif_av_source.ActivePeer();
}
-/*******************************************************************************
- *
- * Function btif_av_stream_ready
- *
- * Description Checks whether AV is ready for starting a stream
- *
- * Returns None
- *
- ******************************************************************************/
+RawAddress btif_av_sink_active_peer(void) { return btif_av_sink.ActivePeer(); }
+
+bool btif_av_is_sink_enabled(void) { return btif_av_sink.Enabled(); }
+
+void btif_av_stream_start(void) {
+ btif_av_source_dispatch_sm_event(btif_av_source_active_peer(),
+ BTIF_AV_START_STREAM_REQ_EVT);
+}
+
+void btif_av_stream_stop(void) {
+ // The active peer might have changed and we might be in the process
+ // of reconfiguring the stream. We need to stop the appopriate peer(s).
+ for (auto it : btif_av_source.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_av_source_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_STOP_STREAM_REQ_EVT);
+ }
+}
+
+void btif_av_stream_suspend(void) {
+ // The active peer might have changed and we might be in the process
+ // of reconfiguring the stream. We need to suspend the appropriate peer(s).
+ for (auto it : btif_av_source.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_av_source_dispatch_sm_event(peer->PeerAddress(),
+ BTIF_AV_SUSPEND_STREAM_REQ_EVT);
+ }
+}
+
+void btif_av_stream_start_offload(void) {
+ btif_av_source_dispatch_sm_event(btif_av_source_active_peer(),
+ BTIF_AV_OFFLOAD_START_REQ_EVT);
+}
bool btif_av_stream_ready(void) {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-
- BTIF_TRACE_DEBUG("%s: sm_handle=%d, state=%d, flags=0x%x", __func__,
- btif_av_cb.sm_handle, state, btif_av_cb.flags);
-
- /* also make sure main adapter is enabled */
+ // Make sure the main adapter is enabled
if (btif_is_enabled() == 0) {
- BTIF_TRACE_EVENT("%s: main adapter not enabled", __func__);
+ BTIF_TRACE_EVENT("%s: Main adapter is not enabled", __func__);
return false;
}
- /* check if we are remotely suspended or stop is pending */
- if (btif_av_cb.flags &
- (BTIF_AV_FLAG_REMOTE_SUSPEND | BTIF_AV_FLAG_PENDING_STOP))
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
return false;
+ }
- return (state == BTIF_AV_STATE_OPENED);
+ int state = peer->StateMachine().StateId();
+ BTIF_TRACE_DEBUG("%s: Peer %s : state=%d, flags=%s", __func__,
+ peer->PeerAddress().ToString().c_str(), state,
+ peer->FlagsToString().c_str());
+ // check if we are remotely suspended or stop is pending
+ if (peer->CheckFlags(BtifAvPeer::kFlagRemoteSuspend |
+ BtifAvPeer::kFlagPendingStop)) {
+ return false;
+ }
+
+ return (state == BtifAvStateMachine::kStateOpened);
}
-/*******************************************************************************
- *
- * Function btif_av_stream_started_ready
- *
- * Description Checks whether AV ready for media start in streaming state
- *
- * Returns None
- *
- ******************************************************************************/
-
bool btif_av_stream_started_ready(void) {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- bool ready = false;
-
- /* disallow media task to start if we have pending actions */
- if (btif_av_cb.flags &
- (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND |
- BTIF_AV_FLAG_PENDING_STOP)) {
- ready = false;
- } else {
- ready = (state == BTIF_AV_STATE_STARTED);
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+ return false;
}
- BTIF_TRACE_WARNING("%s: sm_handle=%d state=%d flags=0x%x ready=%d", __func__,
- btif_av_cb.sm_handle, state, btif_av_cb.flags, ready);
+ int state = peer->StateMachine().StateId();
+ bool ready = false;
+ if (peer->CheckFlags(BtifAvPeer::kFlagLocalSuspendPending |
+ BtifAvPeer::kFlagRemoteSuspend |
+ BtifAvPeer::kFlagPendingStop)) {
+ // Disallow media task to start if we have pending actions
+ ready = false;
+ } else {
+ ready = (state == BtifAvStateMachine::kStateStarted);
+ }
+ BTIF_TRACE_WARNING("%s: Peer %s : state=%d flags=%s ready=%d", __func__,
+ peer->PeerAddress().ToString().c_str(), state,
+ peer->FlagsToString().c_str(), ready);
return ready;
}
-/*******************************************************************************
- *
- * Function btif_dispatch_sm_event
- *
- * Description Send event to AV statemachine
- *
- * Returns None
- *
- ******************************************************************************/
+static void btif_av_source_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event) {
+ BtifAvEvent btif_av_event(event, nullptr, 0);
+ BTIF_TRACE_EVENT("%s: peer_address=%s event=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_av_event.ToString().c_str());
-/* used to pass events to AV statemachine from other tasks */
-void btif_dispatch_sm_event(btif_av_sm_event_t event, void* p_data, int len) {
- /* Switch to BTIF context */
- btif_transfer_context(btif_av_handle_event, event, (char*)p_data, len, NULL);
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SNK, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
}
-/*******************************************************************************
- *
- * Function btif_av_execute_service
- *
- * Description Initializes/Shuts down the service
- *
- * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
- *
- ******************************************************************************/
-bt_status_t btif_av_execute_service(bool b_enable) {
- if (b_enable) {
-/* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
- * handle this request in order to allow incoming connections to succeed.
- * We need to put this back once support for this is added */
+static void btif_av_sink_dispatch_sm_event(const RawAddress& peer_address,
+ btif_av_sm_event_t event) {
+ BtifAvEvent btif_av_event(event, nullptr, 0);
+ BTIF_TRACE_EVENT("%s: peer_address=%s event=%s", __func__,
+ peer_address.ToString().c_str(),
+ btif_av_event.ToString().c_str());
-/* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
- * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
- * be initiated by the app/audioflinger layers */
-/* Support for browsing for SDP record should work only if we enable BROWSE
- * while registering. */
- BTA_AvEnable(BTA_SEC_AUTHENTICATE,
- BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
- BTA_AV_FEAT_NO_SCO_SSPD
+ do_in_jni_thread(FROM_HERE,
+ base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SRC, // peer_sep
+ peer_address, kBtaHandleUnknown, btif_av_event));
+}
+
+bt_status_t btif_av_source_execute_service(bool enable) {
+ BTIF_TRACE_EVENT("%s: Source service: %s", __func__,
+ (enable) ? "enable" : "disable");
+
+ if (enable) {
+ // TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
+ // handle this request in order to allow incoming connections to succeed.
+ // We need to put this back once support for this is added.
+
+ // Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
+ // auto-suspend av streaming on AG events(SCO or Call). The suspend shall
+ // be initiated by the app/audioflinger layers.
+ // Support for browsing for SDP record should work only if we enable BROWSE
+ // while registering.
+ tBTA_AV_FEAT features = BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA |
+ BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_NO_SCO_SSPD;
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
- | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL |
- BTA_AV_FEAT_BROWSE
+ features |= BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_BROWSE;
#endif
- ,
- bte_av_callback);
- BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, NULL,
- UUID_SERVCLASS_AUDIO_SOURCE);
- } else {
- BTA_AvDeregister(btif_av_cb.bta_handle);
- BTA_AvDisable();
+ BTA_AvEnable(BTA_SEC_AUTHENTICATE, features, bta_av_source_callback);
+ btif_av_source.RegisterAllBtaHandles();
+ return BT_STATUS_SUCCESS;
}
+
+ // Disable the service
+ btif_av_source.DeregisterAllBtaHandles();
+ BTA_AvDisable();
return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function btif_av_sink_execute_service
- *
- * Description Initializes/Shuts down the service
- *
- * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
- *
- ******************************************************************************/
-bt_status_t btif_av_sink_execute_service(bool b_enable) {
- if (b_enable) {
- /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
- * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
- * be initiated by the app/audioflinger layers */
- BTA_AvEnable(BTA_SEC_AUTHENTICATE,
- BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT |
- BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
- BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG |
- BTA_AV_FEAT_BROWSE,
- bte_av_callback);
- BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AVK_SERVICE_NAME, 0,
- bte_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);
- } else {
- BTA_AvDeregister(btif_av_cb.bta_handle);
- BTA_AvDisable();
+bt_status_t btif_av_sink_execute_service(bool enable) {
+ BTIF_TRACE_EVENT("%s: Sink service: %s", __func__,
+ (enable) ? "enable" : "disable");
+
+ if (enable) {
+ // Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
+ // auto-suspend AV streaming on AG events (SCO or Call). The suspend shall
+ // be initiated by the app/audioflinger layers.
+ tBTA_AV_FEAT features = BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT |
+ BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
+ BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG |
+ BTA_AV_FEAT_BROWSE;
+ BTA_AvEnable(BTA_SEC_AUTHENTICATE, features, bta_av_sink_callback);
+ btif_av_sink.RegisterAllBtaHandles();
+ return BT_STATUS_SUCCESS;
}
+
+ // Disable the service
+ btif_av_sink.DeregisterAllBtaHandles();
+ BTA_AvDisable();
return BT_STATUS_SUCCESS;
}
-/*******************************************************************************
- *
- * Function btif_av_get_src_interface
- *
- * Description Get the AV callback interface for A2DP source profile
- *
- * Returns btav_source_interface_t
- *
- ******************************************************************************/
+// Get the AV callback interface for A2DP source profile
const btav_source_interface_t* btif_av_get_src_interface(void) {
BTIF_TRACE_EVENT("%s", __func__);
return &bt_av_src_interface;
}
-/*******************************************************************************
- *
- * Function btif_av_get_sink_interface
- *
- * Description Get the AV callback interface for A2DP sink profile
- *
- * Returns btav_sink_interface_t
- *
- ******************************************************************************/
+// Get the AV callback interface for A2DP sink profile
const btav_sink_interface_t* btif_av_get_sink_interface(void) {
BTIF_TRACE_EVENT("%s", __func__);
return &bt_av_sink_interface;
}
-/*******************************************************************************
- *
- * Function btif_av_is_connected
- *
- * Description Checks if av has a connected sink
- *
- * Returns bool
- *
- ******************************************************************************/
bool btif_av_is_connected(void) {
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- return ((state == BTIF_AV_STATE_OPENED) || (state == BTIF_AV_STATE_STARTED));
-}
-
-uint8_t btif_av_get_peer_sep(void) { return btif_av_cb.peer_sep; }
-
-/*******************************************************************************
- *
- * Function btif_av_is_peer_edr
- *
- * Description Check if the connected a2dp device supports
- * EDR or not. Only when connected this function
- * will accurately provide a true capability of
- * remote peer. If not connected it will always be false.
- *
- * Returns true if remote device is capable of EDR
- *
- ******************************************************************************/
-bool btif_av_is_peer_edr(void) {
- ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
-
- if (btif_av_cb.edr)
- return true;
- else
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
return false;
-}
-
-/******************************************************************************
- *
- * Function btif_av_clear_remote_suspend_flag
- *
- * Description Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set
- *
- * Returns void
- *****************************************************************************/
-void btif_av_clear_remote_suspend_flag(void) {
- BTIF_TRACE_DEBUG("%s: flags=0x%x", __func__, btif_av_cb.flags);
- btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-}
-
-/*******************************************************************************
- *
- * Function btif_av_peer_supports_3mbps
- *
- * Description Check if the connected A2DP device supports
- * 3 Mbps EDR. This function only works if connected.
- * If not connected it will always be false.
- *
- * Returns true if remote device is EDR and supports 3 Mbps
- *
- ******************************************************************************/
-bool btif_av_peer_supports_3mbps(void) {
- bool is3mbps = ((btif_av_cb.edr & BTA_AV_EDR_3MBPS) != 0);
- BTIF_TRACE_DEBUG("%s: connected %d, edr_3mbps %d", __func__,
- btif_av_is_connected(), is3mbps);
- return (btif_av_is_connected() && is3mbps);
-}
-
-/*******************************************************************************
- *
- * Function btif_av_move_idle
- *
- * Description Opening state is intermediate state. It cannot handle
- * incoming/outgoing connect/disconnect requests.When ACL
- * is disconnected and we are in opening state then move back
- * to idle state which is proper to handle connections.
- *
- * Returns Void
- *
- ******************************************************************************/
-void btif_av_move_idle(RawAddress bd_addr) {
- /* inform the application that ACL is disconnected and move to idle state */
- btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
- BTIF_TRACE_WARNING("%s: ACL Disconnected state %d bd_addr=%s peer_bda=%s",
- __func__, state, bd_addr.ToString().c_str(),
- btif_av_cb.peer_bda.ToString().c_str());
-
- if (state == BTIF_AV_STATE_OPENING && (bd_addr == btif_av_cb.peer_bda)) {
- BTIF_TRACE_DEBUG(
- "%s: Moving State from Opening to Idle due to ACL disconnect",
- __func__);
- btif_report_connection_state(&(btif_av_cb.peer_bda),
- BTAV_CONNECTION_STATE_DISCONNECTED);
- btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
}
+
+ bool connected = peer->IsConnected();
+ BTIF_TRACE_DEBUG("%s: Peer %s is %s", __func__,
+ peer->PeerAddress().ToString().c_str(),
+ (connected) ? "connected" : "not connected");
+ return connected;
+}
+
+uint8_t btif_av_get_peer_sep(void) {
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+ return AVDT_TSEP_SNK;
+ }
+
+ uint8_t peer_sep = peer->PeerSep();
+ BTIF_TRACE_DEBUG("%s: Peer %s SEP is %s (%d)", __func__,
+ peer->PeerAddress().ToString().c_str(),
+ (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep);
+ return peer_sep;
+}
+
+void btif_av_clear_remote_suspend_flag(void) {
+ BtifAvPeer* peer = btif_av_find_active_peer();
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+ return;
+ }
+
+ BTIF_TRACE_DEBUG("%s: Peer %s : flags=%s are cleared", __func__,
+ peer->PeerAddress().ToString().c_str(),
+ peer->FlagsToString().c_str());
+ peer->ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
+}
+
+void btif_av_avrcp_event_open(const RawAddress& peer_address) {
+ // TODO: We need a better demultipexing mechanism whether the remote device
+ // is an A2DP Source or a Sink.
+ if (btif_av_source.Enabled()) {
+ BtifAvPeer* peer =
+ btif_av_source.FindOrCreatePeer(peer_address, kBtaHandleUnknown);
+ if (peer != nullptr) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
+ return;
+ }
+ } else if (btif_av_sink.Enabled()) {
+ BtifAvPeer* peer =
+ btif_av_sink.FindOrCreatePeer(peer_address, kBtaHandleUnknown);
+ if (peer != nullptr) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
+ return;
+ }
+ }
+ BTIF_TRACE_ERROR("%s: event ignored: cannot find or create peer state for %s",
+ __func__, peer_address.ToString().c_str());
+}
+
+void btif_av_avrcp_event_close(const RawAddress& peer_address) {
+ // TODO: We need a better demultipexing mechanism whether the remote device
+ // is an A2DP Source or a Sink.
+ if (btif_av_source.Enabled()) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_CLOSE_EVT);
+ } else if (btif_av_sink.Enabled()) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_CLOSE_EVT);
+ }
+}
+
+void btif_av_avrcp_event_remote_play(const RawAddress& peer_address) {
+ // TODO: We need a better demultipexing mechanism whether the remote device
+ // is an A2DP Source or a Sink.
+ if (btif_av_source.Enabled()) {
+ btif_av_source_dispatch_sm_event(peer_address,
+ BTIF_AV_AVRCP_REMOTE_PLAY_EVT);
+ } else if (btif_av_sink.Enabled()) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_REMOTE_PLAY_EVT);
+ }
+}
+
+bool btif_av_is_peer_edr(const RawAddress& peer_address) {
+ BtifAvPeer* peer = btif_av_find_peer(peer_address);
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No peer found for peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ return false;
+ }
+ if (!peer->IsConnected()) {
+ BTIF_TRACE_WARNING("%s: Peer %s is not connected", __func__,
+ peer_address.ToString().c_str());
+ return false;
+ }
+
+ bool is_edr = peer->IsEdr();
+ BTIF_TRACE_DEBUG("%s: Peer %s : is_edr=%d", __func__,
+ peer_address.ToString().c_str(), is_edr);
+ return is_edr;
+}
+
+bool btif_av_peer_supports_3mbps(const RawAddress& peer_address) {
+ BtifAvPeer* peer = btif_av_find_peer(peer_address);
+ if (peer == nullptr) {
+ BTIF_TRACE_WARNING("%s: No peer found for peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ return false;
+ }
+
+ bool is3mbps = peer->Is3Mbps();
+ bool is_connected = peer->IsConnected();
+ BTIF_TRACE_DEBUG("%s: Peer %s : connected=%d, edr_3mbps=%d", __func__,
+ peer_address.ToString().c_str(), is_connected, is3mbps);
+ return (is_connected && is3mbps);
+}
+
+void btif_av_acl_disconnected(const RawAddress& peer_address) {
+ // Inform the application that ACL is disconnected and move to idle state
+ BTIF_TRACE_WARNING("%s: Peer %s : ACL Disconnected", __func__,
+ peer_address.ToString().c_str());
+
+ if (btif_av_source.Enabled()) {
+ btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_ACL_DISCONNECTED);
+ } else if (btif_av_sink.Enabled()) {
+ btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_ACL_DISCONNECTED);
+ }
+}
+
+static void btif_debug_av_peer_dump(int fd, const BtifAvPeer& peer) {
+ std::string state_str;
+ int state = peer.StateMachine().StateId();
+ switch (state) {
+ case BtifAvStateMachine::kStateIdle:
+ state_str = "Idle";
+ break;
+ case BtifAvStateMachine::kStateOpening:
+ state_str = "Opening";
+ break;
+ case BtifAvStateMachine::kStateOpened:
+ state_str = "Opened";
+ break;
+ case BtifAvStateMachine::kStateStarted:
+ state_str = "Started";
+ break;
+ case BtifAvStateMachine::kStateClosing:
+ state_str = "Closing";
+ break;
+ default:
+ state_str = "Unknown(" + std::to_string(state) + ")";
+ break;
+ }
+
+ dprintf(fd, " Peer: %s\n", peer.PeerAddress().ToString().c_str());
+ dprintf(fd, " Connected: %s\n", peer.IsConnected() ? "true" : "false");
+ dprintf(fd, " Streaming: %s\n", peer.IsStreaming() ? "true" : "false");
+ dprintf(fd, " SEP: %d(%s)\n", peer.PeerSep(),
+ (peer.IsSource()) ? "Source" : "Sink");
+ dprintf(fd, " State Machine: %s\n", state_str.c_str());
+ dprintf(fd, " Flags: %s\n", peer.FlagsToString().c_str());
+ dprintf(fd, " OpenOnRcTimer: %s\n",
+ alarm_is_scheduled(peer.AvOpenOnRcTimer()) ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " BTA Handle: %d\n", peer.BtaHandle());
+ dprintf(fd, " Peer ID: %d\n", peer.PeerId());
+ dprintf(fd, " EDR: %s\n", peer.IsEdr() ? "true" : "false");
+ dprintf(fd, " Support 3Mbps: %s\n", peer.Is3Mbps() ? "true" : "false");
+ dprintf(fd, " Self Initiated Connection: %s\n",
+ peer.SelfInitiatedConnection() ? "true" : "false");
+}
+
+static void btif_debug_av_source_dump(int fd) {
+ bool enabled = btif_av_source.Enabled();
+
+ dprintf(fd, "\nA2DP Source State: %s\n", (enabled) ? "Enabled" : "Disabled");
+ if (!enabled) return;
+ dprintf(fd, " Active peer: %s\n",
+ btif_av_source.ActivePeer().ToString().c_str());
+ for (auto it : btif_av_source.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_debug_av_peer_dump(fd, *peer);
+ }
+}
+
+static void btif_debug_av_sink_dump(int fd) {
+ bool enabled = btif_av_sink.Enabled();
+
+ dprintf(fd, "\nA2DP Sink State: %s\n", (enabled) ? "Enabled" : "Disabled");
+ if (!enabled) return;
+ dprintf(fd, " Active peer: %s\n",
+ btif_av_sink.ActivePeer().ToString().c_str());
+ dprintf(fd, " Peers:\n");
+ for (auto it : btif_av_sink.Peers()) {
+ const BtifAvPeer* peer = it.second;
+ btif_debug_av_peer_dump(fd, *peer);
+ }
+}
+
+void btif_debug_av_dump(int fd) {
+ btif_debug_av_source_dump(fd);
+ btif_debug_av_sink_dump(fd);
}
diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc
index 48d89c9..4783163 100644
--- a/btif/src/btif_dm.cc
+++ b/btif/src/btif_dm.cc
@@ -49,6 +49,7 @@
#include "bta_closure_api.h"
#include "bta_gatt_api.h"
#include "btif_api.h"
+#include "btif_av.h"
#include "btif_config.h"
#include "btif_dm.h"
#include "btif_hd.h"
@@ -250,7 +251,6 @@
extern bt_status_t btif_hf_client_execute_service(bool b_enable);
extern bt_status_t btif_sdp_execute_service(bool b_enable);
extern int btif_hh_connect(const RawAddress* bd_addr);
-extern void btif_av_move_idle(RawAddress bd_addr);
extern bt_status_t btif_hd_execute_service(bool b_enable);
/******************************************************************************
@@ -304,7 +304,7 @@
bluetooth::headset::ExecuteService(b_enable);
} break;
case BTA_A2DP_SOURCE_SERVICE_ID: {
- btif_av_execute_service(b_enable);
+ btif_av_source_execute_service(b_enable);
} break;
case BTA_A2DP_SINK_SERVICE_ID: {
btif_av_sink_execute_service(b_enable);
@@ -1683,7 +1683,7 @@
case BTA_DM_LINK_DOWN_EVT:
bd_addr = p_data->link_down.bd_addr;
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
- btif_av_move_idle(bd_addr);
+ btif_av_acl_disconnected(bd_addr);
BTIF_TRACE_DEBUG(
"BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
@@ -1891,7 +1891,7 @@
case BTA_DM_ROLE_CHG_EVT:
default:
- BTIF_TRACE_WARNING("btif_dm_cback : unhandled event (%d)", event);
+ BTIF_TRACE_WARNING("%s: unhandled event (%d)", __func__, event);
break;
}
diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc
index e26684b..6ac38fe 100644
--- a/btif/src/btif_rc.cc
+++ b/btif/src/btif_rc.cc
@@ -42,12 +42,14 @@
#include "bta_av_api.h"
#include "btif_av.h"
#include "btif_common.h"
+#include "btif_rc.h"
#include "btif_util.h"
#include "btu.h"
#include "device/include/interop.h"
#include "osi/include/list.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
+
#define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
/*****************************************************************************
@@ -489,13 +491,21 @@
CHECK(bt_rc_callbacks);
btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
- RawAddress avdtp_addr = btif_av_get_addr();
+ RawAddress avdtp_source_active_peer_addr = btif_av_source_active_peer();
+ RawAddress avdtp_sink_active_peer_addr = btif_av_sink_active_peer();
- BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
- avdtp_addr.ToString().c_str(), rc_addr.ToString().c_str());
+ BTIF_TRACE_DEBUG(
+ "%s: AVDTP Source Active Peer Address: %s "
+ "AVDTP Sink Active Peer Address: %s "
+ "AVCTP address: %s",
+ __func__, avdtp_source_active_peer_addr.ToString().c_str(),
+ avdtp_sink_active_peer_addr.ToString().c_str(),
+ rc_addr.ToString().c_str());
if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) ||
- absolute_volume_disabled() || avdtp_addr != rc_addr) {
+ absolute_volume_disabled() ||
+ (avdtp_source_active_peer_addr != rc_addr &&
+ avdtp_sink_active_peer_addr != rc_addr)) {
p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
}
@@ -1072,18 +1082,11 @@
}
}
-/***************************************************************************
- **
- ** Function btif_rc_get_connected_peer
- **
- ** Description Fetches the connected headset's address if any
- **
- ***************************************************************************/
-bool btif_rc_get_connected_peer(RawAddress* peer_addr) {
+bool btif_rc_is_connected_peer(const RawAddress& peer_addr) {
for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
btif_rc_device_cb_t* p_dev = get_connected_device(idx);
- if (p_dev != NULL && (p_dev->rc_connected == TRUE)) {
- *peer_addr = p_dev->rc_addr;
+ if (p_dev != NULL && (p_dev->rc_connected == TRUE) &&
+ peer_addr == p_dev->rc_addr) {
return true;
}
}
diff --git a/btif/src/btif_sm.cc b/btif/src/btif_sm.cc
deleted file mode 100644
index e5a6889..0000000
--- a/btif/src/btif_sm.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2009-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
- *
- * Filename: btif_sm.c
- *
- * Description: Generic BTIF state machine API
- *
- *****************************************************************************/
-
-#define LOG_TAG "bt_btif"
-
-#include "btif_sm.h"
-
-#include "bt_common.h"
-#include "btif_common.h"
-#include "osi/include/allocator.h"
-
-/*****************************************************************************
- * Local type definitions
- *****************************************************************************/
-typedef struct {
- btif_sm_state_t state;
- btif_sm_handler_t* p_handlers;
-} btif_sm_cb_t;
-
-/*****************************************************************************
- * Functions
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * Function btif_sm_init
- *
- * Description Initializes the state machine with the state handlers
- * The caller should ensure that the table and the corresponding
- * states match. The location that 'p_handlers' points to shall
- * be available until the btif_sm_shutdown API is invoked.
- *
- * Returns Returns a pointer to the initialized state machine handle.
- *
- *****************************************************************************/
-
-btif_sm_handle_t btif_sm_init(const btif_sm_handler_t* p_handlers,
- btif_sm_state_t initial_state) {
- if (p_handlers == NULL) {
- BTIF_TRACE_ERROR("%s : p_handlers is NULL", __func__);
- return NULL;
- }
-
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)osi_malloc(sizeof(btif_sm_cb_t));
- p_cb->state = initial_state;
- p_cb->p_handlers = (btif_sm_handler_t*)p_handlers;
-
- /* Send BTIF_SM_ENTER_EVT to the initial state */
- p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL);
-
- return (btif_sm_handle_t)p_cb;
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_shutdown
- *
- * Description Tears down the state machine
- *
- * Returns None
- *
- *****************************************************************************/
-void btif_sm_shutdown(btif_sm_handle_t handle) {
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return;
- }
- osi_free(p_cb);
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_get_state
- *
- * Description Fetches the current state of the state machine
- *
- * Returns Current state
- *
- *****************************************************************************/
-btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) {
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return 0;
- }
-
- return p_cb->state;
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_dispatch
- *
- * Description Dispatches the 'event' along with 'data' to the current state
- * handler
- *
- * Returns BT_STATUS_SUCCESS on success
- * BT_STATUS_UNHANDLED if event was not processed
- * BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event,
- void* data) {
- bt_status_t status = BT_STATUS_SUCCESS;
-
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return BT_STATUS_FAIL;
- }
-
- if (!p_cb->p_handlers[p_cb->state](event, data)) return BT_STATUS_UNHANDLED;
-
- return status;
-}
-
-/*****************************************************************************
- *
- * Function btif_sm_change_state
- *
- * Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT'
- * shall be invoked before exiting the current state. The
- * 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new
- * state
- *
- * Returns BT_STATUS_SUCCESS on success
- * BT_STATUS_UNHANDLED if event was not processed
- * BT_STATUS_FAIL otherwise
- *
- *****************************************************************************/
-bt_status_t btif_sm_change_state(btif_sm_handle_t handle,
- btif_sm_state_t state) {
- bt_status_t status = BT_STATUS_SUCCESS;
- btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;
-
- if (p_cb == NULL) {
- BTIF_TRACE_ERROR("%s : Invalid handle", __func__);
- return BT_STATUS_FAIL;
- }
-
- /* Send exit event to the current state */
- if (!p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL))
- status = BT_STATUS_UNHANDLED;
-
- /* Change to the new state */
- p_cb->state = state;
-
- /* Send enter event to the new state */
- if (!p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL))
- status = BT_STATUS_UNHANDLED;
-
- return status;
-}
diff --git a/btif/test/btif_state_machine_test.cc b/btif/test/btif_state_machine_test.cc
new file mode 100644
index 0000000..d413a4a
--- /dev/null
+++ b/btif/test/btif_state_machine_test.cc
@@ -0,0 +1,261 @@
+/******************************************************************************
+ *
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "btif/include/btif_state_machine.h"
+
+namespace {
+static constexpr uint32_t kInvalidEvent = 0xffffffff;
+static constexpr uint32_t kEventZero = 0;
+static constexpr uint32_t kEventOne = 1;
+static constexpr uint32_t kEventTwo = 2;
+
+static char dataZero = 0;
+static char dataOne = 1;
+static char dataTwo = 2;
+} // namespace
+
+class BtifStateMachineImpl : public BtifStateMachine {
+ public:
+ enum {
+ kStateZero,
+ kStateOne,
+ kStateTwo,
+ };
+
+ class StateZero : public State {
+ public:
+ StateZero(BtifStateMachine& sm)
+ : State(sm, kStateZero),
+ on_enter_(false),
+ on_exit_(false),
+ event_(kInvalidEvent),
+ data_(nullptr) {}
+ void OnEnter() override {
+ on_enter_ = true;
+ on_exit_ = false;
+ }
+ void OnExit() override {
+ on_exit_ = true;
+ on_enter_ = false;
+ }
+ bool ProcessEvent(uint32_t event, void* p_data) override {
+ event_ = event;
+ data_ = p_data;
+ TransitionTo(kStateOne);
+ return true;
+ }
+
+ bool on_enter_;
+ bool on_exit_;
+ uint32_t event_;
+ void* data_;
+ };
+
+ class StateOne : public State {
+ public:
+ StateOne(BtifStateMachine& sm)
+ : State(sm, kStateOne),
+ on_enter_(false),
+ on_exit_(false),
+ event_(kInvalidEvent),
+ data_(nullptr) {}
+ void OnEnter() override {
+ on_enter_ = true;
+ on_exit_ = false;
+ }
+ void OnExit() override {
+ on_exit_ = true;
+ on_enter_ = false;
+ }
+ bool ProcessEvent(uint32_t event, void* p_data) override {
+ event_ = event;
+ data_ = p_data;
+ TransitionTo(kStateTwo);
+ return true;
+ }
+
+ bool on_enter_;
+ bool on_exit_;
+ uint32_t event_;
+ void* data_;
+ };
+
+ class StateTwo : public State {
+ public:
+ StateTwo(BtifStateMachine& sm)
+ : State(sm, kStateTwo),
+ on_enter_(false),
+ on_exit_(false),
+ event_(kInvalidEvent),
+ data_(nullptr) {}
+ void OnEnter() override {
+ on_enter_ = true;
+ on_exit_ = false;
+ }
+ void OnExit() override {
+ on_exit_ = true;
+ on_enter_ = false;
+ }
+ bool ProcessEvent(uint32_t event, void* p_data) override {
+ event_ = event;
+ data_ = p_data;
+ TransitionTo(kStateZero);
+ return true;
+ }
+
+ bool on_enter_;
+ bool on_exit_;
+ uint32_t event_;
+ void* data_;
+ };
+
+ BtifStateMachineImpl() {
+ state_zero_ = new StateZero(*this);
+ state_one_ = new StateOne(*this);
+ state_two_ = new StateTwo(*this);
+
+ AddState(state_zero_);
+ AddState(state_one_);
+ AddState(state_two_);
+ SetInitialState(state_zero_);
+ }
+
+ StateZero* state_zero_;
+ StateOne* state_one_;
+ StateTwo* state_two_;
+};
+
+class BtifStateMachineTest : public ::testing::Test {
+ protected:
+ BtifStateMachineTest() {}
+
+ void SetUp() override { sm_.Start(); }
+
+ void TearDown() override { sm_.Quit(); }
+
+ BtifStateMachineImpl sm_;
+};
+
+TEST_F(BtifStateMachineTest, test_initial_state) {
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+}
+
+TEST_F(BtifStateMachineTest, test_invalid_state) {
+ sm_.Quit();
+ ASSERT_EQ(sm_.kStateInvalid, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+ sm_.Start();
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+}
+
+TEST_F(BtifStateMachineTest, test_transition_to) {
+ // Initial state: StateZero
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_zero_->on_enter_);
+ ASSERT_FALSE(sm_.state_zero_->on_exit_);
+
+ // Transition to StateOne
+ ASSERT_FALSE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+ sm_.TransitionTo(sm_.kStateOne);
+ ASSERT_EQ(sm_.kStateOne, sm_.StateId());
+ ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_zero_->on_exit_);
+ ASSERT_TRUE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+
+ // Transition to StateTwo
+ ASSERT_FALSE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+ sm_.TransitionTo(sm_.kStateTwo);
+ ASSERT_EQ(sm_.kStateTwo, sm_.StateId());
+ ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_one_->on_exit_);
+ ASSERT_TRUE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+}
+
+TEST_F(BtifStateMachineTest, test_process_event) {
+ // Initial state: StateZero
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
+ ASSERT_TRUE(sm_.state_zero_->on_enter_);
+ ASSERT_FALSE(sm_.state_zero_->on_exit_);
+ ASSERT_EQ(sm_.state_zero_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_zero_->data_, nullptr);
+
+ // Process an event and transition to StateOne
+ ASSERT_FALSE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+ ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_one_->data_, nullptr);
+ ASSERT_TRUE(sm_.ProcessEvent(kEventZero, &dataZero));
+ ASSERT_EQ(sm_.kStateOne, sm_.StateId());
+ ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId());
+ // Check StateZero
+ ASSERT_EQ(sm_.state_zero_->event_, kEventZero);
+ ASSERT_EQ(sm_.state_zero_->data_, &dataZero);
+ ASSERT_TRUE(sm_.state_zero_->on_exit_);
+ // Check StateOne
+ ASSERT_TRUE(sm_.state_one_->on_enter_);
+ ASSERT_FALSE(sm_.state_one_->on_exit_);
+ ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_one_->data_, nullptr);
+
+ // Process an event and transition to StateTwo
+ ASSERT_FALSE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+ ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_two_->data_, nullptr);
+ ASSERT_TRUE(sm_.ProcessEvent(kEventOne, &dataOne));
+ ASSERT_EQ(sm_.kStateTwo, sm_.StateId());
+ ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId());
+ // Check StateOne
+ ASSERT_EQ(sm_.state_one_->event_, kEventOne);
+ ASSERT_EQ(sm_.state_one_->data_, &dataOne);
+ ASSERT_TRUE(sm_.state_one_->on_exit_);
+ // Check StateTwo
+ ASSERT_TRUE(sm_.state_two_->on_enter_);
+ ASSERT_FALSE(sm_.state_two_->on_exit_);
+ ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent);
+ ASSERT_EQ(sm_.state_two_->data_, nullptr);
+
+ // Process an event and transition to StateZero
+ // NOTE: StateZero was exited before and has local state
+ ASSERT_FALSE(sm_.state_zero_->on_enter_);
+ ASSERT_TRUE(sm_.state_zero_->on_exit_); // NOTE: already exited before
+ ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before
+ ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before
+ ASSERT_TRUE(sm_.ProcessEvent(kEventTwo, &dataTwo));
+ ASSERT_EQ(sm_.kStateZero, sm_.StateId());
+ ASSERT_EQ(sm_.kStateTwo, sm_.PreviousStateId());
+ // Check StateTwo
+ ASSERT_EQ(sm_.state_two_->event_, kEventTwo);
+ ASSERT_EQ(sm_.state_two_->data_, &dataTwo);
+ ASSERT_TRUE(sm_.state_two_->on_exit_);
+ // Check StateZero
+ ASSERT_TRUE(sm_.state_zero_->on_enter_);
+ ASSERT_FALSE(sm_.state_zero_->on_exit_);
+ ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before
+ ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before
+}
diff --git a/include/hardware/bt_av.h b/include/hardware/bt_av.h
index 873c36a..8c9d1f9 100644
--- a/include/hardware/bt_av.h
+++ b/include/hardware/bt_av.h
@@ -126,25 +126,120 @@
int64_t codec_specific_2; // Codec-specific value 2
int64_t codec_specific_3; // Codec-specific value 3
int64_t codec_specific_4; // Codec-specific value 4
+
+ std::string ToString() const {
+ std::string codec_name_str;
+
+ switch (codec_type) {
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
+ codec_name_str = "SBC";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+ codec_name_str = "AAC";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
+ codec_name_str = "aptX";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
+ codec_name_str = "aptX HD";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
+ codec_name_str = "LDAC";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
+ codec_name_str = "SBC (Sink)";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
+ codec_name_str = "AAC (Sink)";
+ break;
+ case BTAV_A2DP_CODEC_INDEX_MAX:
+ codec_name_str = "Unknown(CODEC_INDEX_MAX)";
+ break;
+ }
+
+ std::string sample_rate_str;
+ AppendCapability(sample_rate_str,
+ (sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE), "NONE");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100),
+ "44100");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000),
+ "48000");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200),
+ "88200");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000),
+ "96000");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400),
+ "176400");
+ AppendCapability(sample_rate_str,
+ (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000),
+ "192000");
+
+ std::string bits_per_sample_str;
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE),
+ "NONE");
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16),
+ "16");
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24),
+ "24");
+ AppendCapability(bits_per_sample_str,
+ (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32),
+ "32");
+
+ std::string channel_mode_str;
+ AppendCapability(channel_mode_str,
+ (channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE),
+ "NONE");
+ AppendCapability(channel_mode_str,
+ (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO),
+ "MONO");
+ AppendCapability(channel_mode_str,
+ (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO),
+ "STEREO");
+
+ return "codec: " + codec_name_str + " sample_rate: " + sample_rate_str +
+ " bits_per_sample: " + bits_per_sample_str +
+ " channel_mode: " + channel_mode_str +
+ " codec_specific_1: " + std::to_string(codec_specific_1) +
+ " codec_specific_2: " + std::to_string(codec_specific_2) +
+ " codec_specific_3: " + std::to_string(codec_specific_3) +
+ " codec_specific_4: " + std::to_string(codec_specific_4);
+ }
+
+ private:
+ static std::string AppendCapability(std::string& result, bool append,
+ const std::string& name) {
+ if (!append) return result;
+ if (!result.empty()) result += "|";
+ result += name;
+ return result;
+ }
} btav_a2dp_codec_config_t;
/** Callback for connection state change.
* state will have one of the values from btav_connection_state_t
*/
-typedef void (*btav_connection_state_callback)(RawAddress* bd_addr,
+typedef void (*btav_connection_state_callback)(const RawAddress& bd_addr,
btav_connection_state_t state);
/** Callback for audiopath state change.
* state will have one of the values from btav_audio_state_t
*/
-typedef void (*btav_audio_state_callback)(RawAddress* bd_addr,
+typedef void (*btav_audio_state_callback)(const RawAddress& bd_addr,
btav_audio_state_t state);
/** Callback for audio configuration change.
* Used only for the A2DP Source interface.
*/
typedef void (*btav_audio_source_config_callback)(
- RawAddress* bd_addr, btav_a2dp_codec_config_t codec_config,
+ const RawAddress& bd_addr, btav_a2dp_codec_config_t codec_config,
std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities);
@@ -153,7 +248,7 @@
* sample_rate: sample rate in Hz
* channel_count: number of channels (1 for mono, 2 for stereo)
*/
-typedef void (*btav_audio_sink_config_callback)(RawAddress* bd_addr,
+typedef void (*btav_audio_sink_config_callback)(const RawAddress& bd_addr,
uint32_t sample_rate,
uint8_t channel_count);
@@ -198,13 +293,17 @@
std::vector<btav_a2dp_codec_config_t> codec_priorities);
/** connect to headset */
- bt_status_t (*connect)(RawAddress* bd_addr);
+ bt_status_t (*connect)(const RawAddress& bd_addr);
/** dis-connect from headset */
- bt_status_t (*disconnect)(RawAddress* bd_addr);
+ bt_status_t (*disconnect)(const RawAddress& bd_addr);
+
+ /** sets the connected device as active */
+ bt_status_t (*set_active_device)(const RawAddress& bd_addr);
/** configure the codecs settings preferences */
bt_status_t (*config_codec)(
+ const RawAddress& bd_addr,
std::vector<btav_a2dp_codec_config_t> codec_preferences);
/** Closes the interface. */
@@ -223,10 +322,10 @@
bt_status_t (*init)(btav_sink_callbacks_t* callbacks);
/** connect to headset */
- bt_status_t (*connect)(RawAddress* bd_addr);
+ bt_status_t (*connect)(const RawAddress& bd_addr);
/** dis-connect from headset */
- bt_status_t (*disconnect)(RawAddress* bd_addr);
+ bt_status_t (*disconnect)(const RawAddress& bd_addr);
/** Closes the interface. */
void (*cleanup)(void);
diff --git a/include/hardware/bt_rc.h b/include/hardware/bt_rc.h
index a965a94..a79156c 100644
--- a/include/hardware/bt_rc.h
+++ b/include/hardware/bt_rc.h
@@ -20,7 +20,7 @@
__BEGIN_DECLS
/* Change this macro to use multiple RC */
-#define BT_RC_NUM_APP 1
+#define BT_RC_NUM_APP 12
/* Macros */
#define BTRC_MAX_ATTR_STR_LEN (1 << 16)
diff --git a/internal_include/bt_target.h b/internal_include/bt_target.h
index 1b12e37..e81898b 100644
--- a/internal_include/bt_target.h
+++ b/internal_include/bt_target.h
@@ -480,14 +480,14 @@
/* The maximum number of simultaneous links that L2CAP can support. */
#ifndef MAX_ACL_CONNECTIONS
-#define MAX_L2CAP_LINKS 7
+#define MAX_L2CAP_LINKS 13
#else
#define MAX_L2CAP_LINKS MAX_ACL_CONNECTIONS
#endif
/* The maximum number of simultaneous channels that L2CAP can support. */
#ifndef MAX_L2CAP_CHANNELS
-#define MAX_L2CAP_CHANNELS 16
+#define MAX_L2CAP_CHANNELS 32
#endif
/* The maximum number of simultaneous applications that can register with L2CAP.
@@ -995,7 +995,7 @@
/* Number of simultaneous links to different peer devices. */
#ifndef AVDT_NUM_LINKS
-#define AVDT_NUM_LINKS 2
+#define AVDT_NUM_LINKS 6
#endif
/* Number of simultaneous stream endpoints. */
@@ -1005,7 +1005,7 @@
/* Number of transport channels setup by AVDT for all media streams */
#ifndef AVDT_NUM_TC_TBL
-#define AVDT_NUM_TC_TBL 6
+#define AVDT_NUM_TC_TBL (AVDT_NUM_SEPS + AVDT_NUM_LINKS)
#endif
/* Maximum size in bytes of the content protection information element. */
@@ -1203,12 +1203,12 @@
/* Number of simultaneous ACL links to different peer devices. */
#ifndef AVCT_NUM_LINKS
-#define AVCT_NUM_LINKS 2
+#define AVCT_NUM_LINKS 6
#endif
/* Number of simultaneous AVCTP connections. */
#ifndef AVCT_NUM_CONN
-#define AVCT_NUM_CONN 3
+#define AVCT_NUM_CONN 14 // 2 * MaxDevices + 2
#endif
/******************************************************************************
diff --git a/internal_include/bt_trace.h b/internal_include/bt_trace.h
index 640ed0a..a0c01f7 100644
--- a/internal_include/bt_trace.h
+++ b/internal_include/bt_trace.h
@@ -478,27 +478,27 @@
/* AVDTP */
#define AVDT_TRACE_ERROR(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_ERROR) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_ERROR, ##__VA_ARGS__); \
}
#define AVDT_TRACE_WARNING(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_WARNING) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_WARNING, ##__VA_ARGS__); \
}
#define AVDT_TRACE_EVENT(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_EVENT) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_EVENT, ##__VA_ARGS__); \
}
#define AVDT_TRACE_DEBUG(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_DEBUG) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_DEBUG, ##__VA_ARGS__); \
}
#define AVDT_TRACE_API(...) \
{ \
- if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API) \
+ if (avdtp_cb.TraceLevel() >= BT_TRACE_LEVEL_API) \
BT_TRACE(TRACE_LAYER_AVP, TRACE_TYPE_API, ##__VA_ARGS__); \
}
diff --git a/main/Android.bp b/main/Android.bp
index 06b2086..3661458 100644
--- a/main/Android.bp
+++ b/main/Android.bp
@@ -91,6 +91,8 @@
defaults: ["fluoride_defaults"],
srcs: [
+ "bte_conf.cc",
+ "bte_init.cc",
"bte_init_cpp_logging.cc",
"bte_logmsg.cc",
"bte_main.cc",
diff --git a/stack/a2dp/a2dp_aac.cc b/stack/a2dp/a2dp_aac.cc
index 9bb67ea..93307c8 100644
--- a/stack/a2dp/a2dp_aac.cc
+++ b/stack/a2dp/a2dp_aac.cc
@@ -680,7 +680,7 @@
const char* A2DP_CodecIndexStrAacSink(void) { return "AAC SINK"; }
-bool A2DP_InitCodecConfigAac(tAVDT_CFG* p_cfg) {
+bool A2DP_InitCodecConfigAac(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aac_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
@@ -697,7 +697,7 @@
return true;
}
-bool A2DP_InitCodecConfigAacSink(tAVDT_CFG* p_cfg) {
+bool A2DP_InitCodecConfigAacSink(AvdtpSepConfig* p_cfg) {
return A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aac_sink_caps,
p_cfg->codec_info) == A2DP_SUCCESS;
}
diff --git a/stack/a2dp/a2dp_codec_config.cc b/stack/a2dp/a2dp_codec_config.cc
index b01c623..08dc5ca 100644
--- a/stack/a2dp/a2dp_codec_config.cc
+++ b/stack/a2dp/a2dp_codec_config.cc
@@ -1236,7 +1236,7 @@
}
bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg) {
+ AvdtpSepConfig* p_cfg) {
LOG_VERBOSE(LOG_TAG, "%s: codec %s", __func__,
A2DP_CodecIndexStr(codec_index));
diff --git a/stack/a2dp/a2dp_sbc.cc b/stack/a2dp/a2dp_sbc.cc
index 38e1b3b..400d6d9 100644
--- a/stack/a2dp/a2dp_sbc.cc
+++ b/stack/a2dp/a2dp_sbc.cc
@@ -857,7 +857,7 @@
const char* A2DP_CodecIndexStrSbcSink(void) { return "SBC SINK"; }
-bool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg) {
+bool A2DP_InitCodecConfigSbc(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
@@ -874,7 +874,7 @@
return true;
}
-bool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg) {
+bool A2DP_InitCodecConfigSbcSink(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_sink_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
diff --git a/stack/a2dp/a2dp_vendor.cc b/stack/a2dp/a2dp_vendor.cc
index 2b874e3..57b7a25 100644
--- a/stack/a2dp/a2dp_vendor.cc
+++ b/stack/a2dp/a2dp_vendor.cc
@@ -518,7 +518,7 @@
}
bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg) {
+ AvdtpSepConfig* p_cfg) {
// Add checks based on codec_index
switch (codec_index) {
case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
diff --git a/stack/a2dp/a2dp_vendor_aptx.cc b/stack/a2dp/a2dp_vendor_aptx.cc
index b22efab..cf136e3 100644
--- a/stack/a2dp/a2dp_vendor_aptx.cc
+++ b/stack/a2dp/a2dp_vendor_aptx.cc
@@ -387,7 +387,7 @@
const char* A2DP_VendorCodecIndexStrAptx(void) { return "aptX"; }
-bool A2DP_VendorInitCodecConfigAptx(tAVDT_CFG* p_cfg) {
+bool A2DP_VendorInitCodecConfigAptx(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoAptx(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aptx_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd.cc b/stack/a2dp/a2dp_vendor_aptx_hd.cc
index 3291947..907712c 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd.cc
@@ -404,7 +404,7 @@
const char* A2DP_VendorCodecIndexStrAptxHd(void) { return "aptX-HD"; }
-bool A2DP_VendorInitCodecConfigAptxHd(tAVDT_CFG* p_cfg) {
+bool A2DP_VendorInitCodecConfigAptxHd(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoAptxHd(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aptx_hd_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
diff --git a/stack/a2dp/a2dp_vendor_ldac.cc b/stack/a2dp/a2dp_vendor_ldac.cc
index 6eeadb8..7f76e1f 100644
--- a/stack/a2dp/a2dp_vendor_ldac.cc
+++ b/stack/a2dp/a2dp_vendor_ldac.cc
@@ -468,7 +468,7 @@
const char* A2DP_VendorCodecIndexStrLdac(void) { return "LDAC"; }
-bool A2DP_VendorInitCodecConfigLdac(tAVDT_CFG* p_cfg) {
+bool A2DP_VendorInitCodecConfigLdac(AvdtpSepConfig* p_cfg) {
if (A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_ldac_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
diff --git a/stack/avdt/avdt_ad.cc b/stack/avdt/avdt_ad.cc
index bedfc58..cc994b0 100644
--- a/stack/avdt/avdt_ad.cc
+++ b/stack/avdt/avdt_ad.cc
@@ -35,6 +35,24 @@
#include "l2cdefs.h"
#include "osi/include/osi.h"
+AvdtpScb* AvdtpAdaptationLayer::LookupAvdtpScb(
+ const AvdtpTransportChannel& tc) {
+ if (tc.ccb_idx >= AVDT_NUM_LINKS) {
+ AVDT_TRACE_ERROR("%s: AvdtpScb entry not found: invalid ccb_idx:%d",
+ __func__, tc.ccb_idx);
+ return nullptr;
+ }
+ if (tc.tcid >= AVDT_NUM_RT_TBL) {
+ AVDT_TRACE_ERROR("%s: AvdtpScb entry not found: invalid tcid:%d", __func__,
+ tc.tcid);
+ return nullptr;
+ }
+ const AvdtpRoutingEntry& re = rt_tbl[tc.ccb_idx][tc.tcid];
+ AVDT_TRACE_DEBUG("%s: ccb_idx:%d tcid:%d scb_hdl:%d", __func__, tc.ccb_idx,
+ tc.tcid, re.scb_hdl);
+ return avdt_scb_by_hdl(re.scb_hdl);
+}
+
/*******************************************************************************
*
* Function avdt_ad_type_to_tcid
@@ -45,19 +63,19 @@
* Returns TCID value.
*
******************************************************************************/
-uint8_t avdt_ad_type_to_tcid(uint8_t type, tAVDT_SCB* p_scb) {
- uint8_t scb_idx;
-
+uint8_t avdt_ad_type_to_tcid(uint8_t type, AvdtpScb* p_scb) {
if (type == AVDT_CHAN_SIG) {
return 0;
- } else {
- scb_idx = avdt_scb_to_hdl(p_scb) - 1;
- /*
- AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx *
- (AVDT_CHAN_NUM_TYPES - 1)) + type));
- */
- return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type);
}
+ // The SCB Handle is unique in the [1, AVDT_NUM_LINKS * AVDT_NUM_SEPS]
+ // range. The scb_idx computed here is the SCB index for the corresponding
+ // SEP, and it is in the range [0, AVDT_NUM_SEPS) for a particular link.
+ uint8_t scb_idx = (avdt_scb_to_hdl(p_scb) - 1) % AVDT_NUM_LINKS;
+ // There are AVDT_CHAN_NUM_TYPES channel types per SEP. Here we compute
+ // the type index (TCID) from the SEP index and the type itself.
+ uint8_t tcid = (scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type;
+ AVDT_TRACE_DEBUG("%s: type:%d, tcid: %d", __func__, type, tcid);
+ return tcid;
}
/*******************************************************************************
@@ -99,8 +117,8 @@
******************************************************************************/
void avdt_ad_init(void) {
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
- memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD));
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
+ avdtp_cb.ad.Reset();
/* make sure the peer_mtu is a valid value */
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
@@ -121,10 +139,10 @@
* first matching entry (there could be more than one).
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_by_st(uint8_t type, tAVDT_CCB* p_ccb,
- uint8_t state) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_by_st(uint8_t type, AvdtpCcb* p_ccb,
+ uint8_t state) {
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
uint8_t ccb_idx;
if (p_ccb == NULL) {
@@ -173,13 +191,13 @@
* Returns Pointer to entry.
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_by_lcid(uint16_t lcid) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_by_lcid(uint16_t lcid) {
uint8_t idx;
- idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
+ idx = avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
if (idx < AVDT_NUM_TC_TBL) {
- return &avdt_cb.ad.tc_tbl[idx];
+ return &avdtp_cb.ad.tc_tbl[idx];
} else {
return NULL;
}
@@ -196,11 +214,11 @@
* Returns Pointer to transport channel table entry.
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_by_type(uint8_t type, tAVDT_CCB* p_ccb,
- tAVDT_SCB* p_scb) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_by_type(uint8_t type, AvdtpCcb* p_ccb,
+ AvdtpScb* p_scb) {
uint8_t tcid;
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
uint8_t ccb_idx = avdt_ccb_to_idx(p_ccb);
/* get tcid from type, scb */
@@ -227,9 +245,9 @@
* Returns Pointer to entry.
*
******************************************************************************/
-tAVDT_TC_TBL* avdt_ad_tc_tbl_alloc(tAVDT_CCB* p_ccb) {
+AvdtpTransportChannel* avdt_ad_tc_tbl_alloc(AvdtpCcb* p_ccb) {
int i;
- tAVDT_TC_TBL* p_tbl = avdt_cb.ad.tc_tbl;
+ AvdtpTransportChannel* p_tbl = avdtp_cb.ad.tc_tbl;
/* find next free entry in tc table */
for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
@@ -259,10 +277,10 @@
* Returns Index value.
*
******************************************************************************/
-uint8_t avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL* p_tbl) {
- AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdt_cb.ad.tc_tbl));
+uint8_t avdt_ad_tc_tbl_to_idx(AvdtpTransportChannel* p_tbl) {
+ AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d", (p_tbl - avdtp_cb.ad.tc_tbl));
/* use array arithmetic to determine index */
- return (uint8_t)(p_tbl - avdt_cb.ad.tc_tbl);
+ return (uint8_t)(p_tbl - avdtp_cb.ad.tc_tbl);
}
/*******************************************************************************
@@ -279,9 +297,10 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_close_ind(tAVDT_TC_TBL* p_tbl, UNUSED_ATTR uint16_t reason) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_close_ind(AvdtpTransportChannel* p_tbl,
+ UNUSED_ATTR uint16_t reason) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
tAVDT_SCB_TC_CLOSE close;
close.old_tc_state = p_tbl->state;
@@ -290,26 +309,27 @@
p_tbl->cfg_flags = 0;
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
- AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d", p_tbl->tcid,
+ AVDT_TRACE_DEBUG("%s: tcid: %d, old: %d", __func__, p_tbl->tcid,
close.old_tc_state);
/* if signaling channel, notify ccb that channel open */
if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
+ return;
}
/* if media or other channel, notify scb that channel close */
- else {
- /* look up scb in stream routing table by ccb, tcid */
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
- if (p_scb != NULL) {
- close.tcid = p_tbl->tcid;
- close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
- tAVDT_SCB_EVT avdt_scb_evt;
- avdt_scb_evt.close = close;
- avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, &avdt_scb_evt);
- }
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ return;
}
+ close.tcid = p_tbl->tcid;
+ close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
+ tAVDT_SCB_EVT avdt_scb_evt;
+ avdt_scb_evt.close = close;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, &avdt_scb_evt);
}
/*******************************************************************************
@@ -324,18 +344,22 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_open_ind(tAVDT_TC_TBL* p_tbl) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_open_ind(AvdtpTransportChannel* p_tbl) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
tAVDT_OPEN open;
tAVDT_EVT_HDR evt;
+ AVDT_TRACE_DEBUG("%s: p_tbl:%p state:%d ccb_idx:%d tcid:%d scb_hdl:%d",
+ __func__, p_tbl, p_tbl->state, p_tbl->ccb_idx, p_tbl->tcid,
+ avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
+
p_tbl->state = AVDT_AD_ST_OPEN;
/* if signaling channel, notify ccb that channel open */
if (p_tbl->tcid == 0) {
/* set the signal channel to use high priority within the ACL link */
- L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid,
+ L2CA_SetTxPriority(avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid,
L2CAP_CHNL_PRIORITY_HIGH);
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
@@ -348,23 +372,23 @@
tAVDT_CCB_EVT avdt_ccb_evt;
avdt_ccb_evt.msg.hdr = evt;
avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, &avdt_ccb_evt);
+ return;
}
/* if media or other channel, notify scb that channel open */
- else {
- /* look up scb in stream routing table by ccb, tcid */
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
-
- /* put lcid in event data */
- if (p_scb != NULL) {
- open.peer_mtu = p_tbl->peer_mtu;
- open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
- open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
- tAVDT_SCB_EVT avdt_scb_evt;
- avdt_scb_evt.open = open;
- avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, &avdt_scb_evt);
- }
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ return;
}
+ /* put lcid in event data */
+ open.peer_mtu = p_tbl->peer_mtu;
+ open.lcid = avdtp_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
+ open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
+ tAVDT_SCB_EVT avdt_scb_evt;
+ avdt_scb_evt.open = open;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, &avdt_scb_evt);
}
/*******************************************************************************
@@ -381,9 +405,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_cong_ind(tAVDT_TC_TBL* p_tbl, bool is_congested) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_cong_ind(AvdtpTransportChannel* p_tbl, bool is_congested) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
/* if signaling channel, notify ccb of congestion */
if (p_tbl->tcid == 0) {
@@ -391,18 +415,19 @@
tAVDT_CCB_EVT avdt_ccb_evt;
avdt_ccb_evt.llcong = is_congested;
avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, &avdt_ccb_evt);
+ return;
}
/* if media or other channel, notify scb that channel open */
- else {
- /* look up scb in stream routing table by ccb, tcid */
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
- if (p_scb != NULL) {
- tAVDT_SCB_EVT avdt_scb_evt;
- avdt_scb_evt.llcong = is_congested;
- avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, &avdt_scb_evt);
- }
+ /* look up scb in stream routing table by ccb, tcid */
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ return;
}
+ tAVDT_SCB_EVT avdt_scb_evt;
+ avdt_scb_evt.llcong = is_congested;
+ avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, &avdt_scb_evt);
}
/*******************************************************************************
@@ -417,9 +442,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_tc_data_ind(tAVDT_TC_TBL* p_tbl, BT_HDR* p_buf) {
- tAVDT_CCB* p_ccb;
- tAVDT_SCB* p_scb;
+void avdt_ad_tc_data_ind(AvdtpTransportChannel* p_tbl, BT_HDR* p_buf) {
+ AvdtpCcb* p_ccb;
+ AvdtpScb* p_scb;
/* store type (media, recovery, reporting) */
p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);
@@ -428,18 +453,18 @@
if (p_tbl->tcid == 0) {
p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
avdt_msg_ind(p_ccb, p_buf);
+ return;
}
/* if media or other channel, send event to scb */
- else {
- p_scb =
- avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
- if (p_scb != NULL) {
- avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT*)&p_buf);
- } else {
- osi_free(p_buf);
- AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
- }
+ p_scb = avdtp_cb.ad.LookupAvdtpScb(*p_tbl);
+ if (p_scb == nullptr) {
+ AVDT_TRACE_ERROR("%s: Cannot find AvdtScb entry: ccb_idx:%d tcid:%d",
+ __func__, p_tbl->ccb_idx, p_tbl->tcid);
+ osi_free(p_buf);
+ AVDT_TRACE_ERROR("%s: buffer freed", __func__);
+ return;
}
+ avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT*)&p_buf);
}
/*******************************************************************************
@@ -458,14 +483,14 @@
* AVDT_AD_FAILED, if error
*
******************************************************************************/
-uint8_t avdt_ad_write_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb,
+uint8_t avdt_ad_write_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
BT_HDR* p_buf) {
uint8_t tcid;
/* get tcid from type, scb */
tcid = avdt_ad_type_to_tcid(type, p_scb);
- return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid,
+ return L2CA_DataWrite(avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid,
p_buf);
}
@@ -485,9 +510,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_open_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb,
+void avdt_ad_open_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
uint8_t role) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
uint16_t lcid;
p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
@@ -502,17 +527,17 @@
if (type == AVDT_CHAN_SIG) {
/* if signaling, get mtu from registration control block */
- p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
+ p_tbl->my_mtu = avdtp_cb.rcb.ctrl_mtu;
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
} else {
/* otherwise get mtu from scb */
- p_tbl->my_mtu = p_scb->cs.mtu;
- p_tbl->my_flush_to = p_scb->cs.flush_to;
+ p_tbl->my_mtu = p_scb->stream_config.mtu;
+ p_tbl->my_flush_to = p_scb->stream_config.flush_to;
/* also set scb_hdl in rt_tbl */
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl =
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl =
avdt_scb_to_hdl(p_scb);
- AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
+ AVDT_TRACE_DEBUG("avdtp_cb.ad.rt_tbl[%d][%d].scb_hdl = %d",
avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
avdt_scb_to_hdl(p_scb));
}
@@ -529,14 +554,14 @@
lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr);
if (lcid != 0) {
/* if connect req ok, store tcid in lcid table */
- avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
+ avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
avdt_ad_tc_tbl_to_idx(p_tbl);
- AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d",
+ AVDT_TRACE_DEBUG("avdtp_cb.ad.lcid_tbl[%d] = %d",
(lcid - L2CAP_BASE_APPL_CID),
avdt_ad_tc_tbl_to_idx(p_tbl));
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
- AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
+ AVDT_TRACE_DEBUG("avdtp_cb.ad.rt_tbl[%d][%d].lcid = 0x%x",
avdt_ccb_to_idx(p_ccb), p_tbl->tcid, lcid);
} else {
/* if connect req failed, call avdt_ad_tc_close_ind() */
@@ -557,9 +582,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ad_close_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb) {
+void avdt_ad_close_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb) {
uint8_t tcid;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d", p_tbl->state);
@@ -577,6 +602,6 @@
tcid = avdt_ad_type_to_tcid(type, p_scb);
/* call l2cap disconnect req */
- L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
+ L2CA_DisconnectReq(avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
}
}
diff --git a/stack/avdt/avdt_api.cc b/stack/avdt/avdt_api.cc
index e1277d0..a635567 100644
--- a/stack/avdt/avdt_api.cc
+++ b/stack/avdt/avdt_api.cc
@@ -34,11 +34,11 @@
#include "l2c_api.h"
#include "stack/include/a2dp_codec_api.h"
-/* Control block for AVDT */
-tAVDT_CB avdt_cb;
+/* Control block for AVDTP */
+AvdtpCb avdtp_cb;
void avdt_ccb_idle_ccb_timer_timeout(void* data) {
- tAVDT_CCB* p_ccb = (tAVDT_CCB*)data;
+ AvdtpCcb* p_ccb = (AvdtpCcb*)data;
uint8_t avdt_event = AVDT_CCB_IDLE_TOUT_EVT;
uint8_t err_code = AVDT_ERR_TIMEOUT;
@@ -48,7 +48,7 @@
}
void avdt_ccb_ret_ccb_timer_timeout(void* data) {
- tAVDT_CCB* p_ccb = (tAVDT_CCB*)data;
+ AvdtpCcb* p_ccb = (AvdtpCcb*)data;
uint8_t avdt_event = AVDT_CCB_RET_TOUT_EVT;
uint8_t err_code = AVDT_ERR_TIMEOUT;
@@ -58,7 +58,7 @@
}
void avdt_ccb_rsp_ccb_timer_timeout(void* data) {
- tAVDT_CCB* p_ccb = (tAVDT_CCB*)data;
+ AvdtpCcb* p_ccb = (AvdtpCcb*)data;
uint8_t avdt_event = AVDT_CCB_RSP_TOUT_EVT;
uint8_t err_code = AVDT_ERR_TIMEOUT;
@@ -68,7 +68,7 @@
}
void avdt_scb_transport_channel_timer_timeout(void* data) {
- tAVDT_SCB* p_scb = (tAVDT_SCB*)data;
+ AvdtpScb* p_scb = (AvdtpScb*)data;
uint8_t avdt_event = AVDT_SCB_TC_TOUT_EVT;
avdt_scb_event(p_scb, avdt_event, NULL);
@@ -88,7 +88,7 @@
* Returns void
*
******************************************************************************/
-void AVDT_Register(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback) {
+void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback) {
/* register PSM with L2CAP */
L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl);
@@ -116,8 +116,8 @@
avdt_ad_init();
/* copy registration struct */
- memcpy(&avdt_cb.rcb, p_reg, sizeof(tAVDT_REG));
- avdt_cb.p_conn_cback = p_cback;
+ avdtp_cb.rcb = *p_reg;
+ avdtp_cb.p_conn_cback = p_cback;
}
/*******************************************************************************
@@ -142,7 +142,7 @@
void AVDT_AbortReq(uint8_t handle) {
AVDT_TRACE_WARNING("%s: handle=%d", __func__, handle);
- tAVDT_SCB* p_scb = avdt_scb_by_hdl(handle);
+ AvdtpScb* p_scb = avdt_scb_by_hdl(handle);
if (p_scb != NULL) {
avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_REQ_EVT, NULL);
} else {
@@ -164,20 +164,21 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_CreateStream(uint8_t* p_handle, tAVDT_CS* p_cs) {
+uint16_t AVDT_CreateStream(uint8_t peer_id, uint8_t* p_handle,
+ const AvdtpStreamConfig& avdtp_stream_config) {
uint16_t result = AVDT_SUCCESS;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
- AVDT_TRACE_DEBUG("%s", __func__);
+ AVDT_TRACE_DEBUG("%s: peer_id=%d", __func__, peer_id);
/* Verify parameters; if invalid, return failure */
- if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) ||
- (p_cs->p_ctrl_cback == NULL)) {
+ if (((avdtp_stream_config.cfg.psc_mask & (~AVDT_PSC)) != 0) ||
+ (avdtp_stream_config.p_avdt_ctrl_cback == NULL)) {
result = AVDT_BAD_PARAMS;
}
/* Allocate scb; if no scbs, return failure */
else {
- p_scb = avdt_scb_alloc(p_cs);
+ p_scb = avdt_scb_alloc(peer_id, avdtp_stream_config);
if (p_scb == NULL) {
result = AVDT_NO_RESOURCES;
} else {
@@ -185,7 +186,8 @@
}
}
- AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
+ AVDT_TRACE_DEBUG("%s: result=%d handle=%d scb_index=%d", __func__, result,
+ *p_handle, avdtp_stream_config.scb_index);
return result;
}
@@ -206,7 +208,7 @@
******************************************************************************/
uint16_t AVDT_RemoveStream(uint8_t handle) {
uint16_t result = AVDT_SUCCESS;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle);
@@ -250,9 +252,10 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr, tAVDT_SEP_INFO* p_sep_info,
- uint8_t max_seps, tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB* p_ccb;
+uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr, uint8_t channel_index,
+ tAVDT_SEP_INFO* p_sep_info, uint8_t max_seps,
+ tAVDT_CTRL_CBACK* p_cback) {
+ AvdtpCcb* p_ccb;
uint16_t result = AVDT_SUCCESS;
tAVDT_CCB_EVT evt;
@@ -261,7 +264,7 @@
/* find channel control block for this bd addr; if none, allocate one */
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -291,15 +294,15 @@
*
* Function avdt_get_cap_req
*
- * Description internal function to serve both AVDT_GetCapReq and
- * AVDT_GetAllCapReq
+ * Description internal function to serve AVDT_GetCapReq
*
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
static uint16_t avdt_get_cap_req(const RawAddress& bd_addr,
+ uint8_t channel_index,
tAVDT_CCB_API_GETCAP* p_evt) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
uint16_t result = AVDT_SUCCESS;
AVDT_TRACE_DEBUG("%s", __func__);
@@ -314,7 +317,7 @@
else {
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -362,60 +365,23 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback) {
+uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t channel_index,
+ uint8_t seid, AvdtpSepConfig* p_cfg,
+ tAVDT_CTRL_CBACK* p_cback, bool get_all_cap) {
tAVDT_CCB_API_GETCAP getcap;
uint16_t result = AVDT_SUCCESS;
AVDT_TRACE_DEBUG("%s", __func__);
getcap.single.seid = seid;
- getcap.single.sig_id = AVDT_SIG_GETCAP;
+ if (get_all_cap) {
+ getcap.single.sig_id = AVDT_SIG_GET_ALLCAP;
+ } else {
+ getcap.single.sig_id = AVDT_SIG_GETCAP;
+ }
getcap.p_cfg = p_cfg;
getcap.p_cback = p_cback;
- result = avdt_get_cap_req(bd_addr, &getcap);
-
- AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
-
- return result;
-}
-
-/*******************************************************************************
- *
- * Function AVDT_GetAllCapReq
- *
- * Description This function initiates a connection to the AVDTP service
- * on the peer device, if not already present, and gets the
- * capabilities of a stream endpoint on the peer device.
- * This function can be called at any time regardless of
- * whether there is an AVDTP connection to the peer device.
- *
- * When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
- * sent to the application via its callback function. The
- * application must not call AVDT_GetCapReq() or
- * AVDT_DiscoverReq() again until the procedure is complete.
- *
- * The memory pointed to by p_cfg is allocated by the
- * application. This memory is written to by AVDTP as part
- * of the get capabilities procedure. This memory must
- * remain accessible until the application receives
- * the AVDT_GETCAP_CFM_EVT.
- *
- * Returns AVDT_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-uint16_t AVDT_GetAllCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB_API_GETCAP getcap;
- uint16_t result = AVDT_SUCCESS;
-
- AVDT_TRACE_DEBUG("%s", __func__);
-
- getcap.single.seid = seid;
- getcap.single.sig_id = AVDT_SIG_GET_ALLCAP;
- getcap.p_cfg = p_cfg;
- getcap.p_cback = p_cback;
- result = avdt_get_cap_req(bd_addr, &getcap);
+ result = avdt_get_cap_req(bd_addr, channel_index, &getcap);
AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
@@ -434,7 +400,7 @@
*
******************************************************************************/
uint16_t AVDT_DelayReport(uint8_t handle, uint8_t seid, uint16_t delay) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -472,10 +438,11 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg) {
- tAVDT_CCB* p_ccb = NULL;
- tAVDT_SCB* p_scb = NULL;
+uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t channel_index, uint8_t seid,
+ AvdtpSepConfig* p_cfg) {
+ AvdtpCcb* p_ccb = NULL;
+ AvdtpScb* p_scb = NULL;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -495,7 +462,7 @@
else {
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -534,13 +501,13 @@
******************************************************************************/
uint16_t AVDT_ConfigRsp(uint8_t handle, uint8_t label, uint8_t error_code,
uint8_t category) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_SCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
uint8_t event_code;
- AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d category=%d", __func__,
- handle, label, error_code, category);
+ AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=0x%x category=%d",
+ __func__, handle, label, error_code, category);
/* map handle to scb */
p_scb = avdt_scb_by_hdl(handle);
@@ -587,7 +554,7 @@
*
******************************************************************************/
uint16_t AVDT_StartReq(uint8_t* p_handles, uint8_t num_handles) {
- tAVDT_SCB* p_scb = NULL;
+ AvdtpScb* p_scb = NULL;
tAVDT_CCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
int i;
@@ -639,7 +606,7 @@
*
******************************************************************************/
uint16_t AVDT_SuspendReq(uint8_t* p_handles, uint8_t num_handles) {
- tAVDT_SCB* p_scb = NULL;
+ AvdtpScb* p_scb = NULL;
tAVDT_CCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
int i;
@@ -690,7 +657,7 @@
*
******************************************************************************/
uint16_t AVDT_CloseReq(uint8_t handle) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
AVDT_TRACE_DEBUG("%s: handle=%d", __func__, handle);
@@ -727,8 +694,8 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_ReconfigReq(uint8_t handle, tAVDT_CFG* p_cfg) {
- tAVDT_SCB* p_scb;
+uint16_t AVDT_ReconfigReq(uint8_t handle, AvdtpSepConfig* p_cfg) {
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -766,12 +733,12 @@
******************************************************************************/
uint16_t AVDT_ReconfigRsp(uint8_t handle, uint8_t label, uint8_t error_code,
uint8_t category) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_SCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
- AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d category=%d", __func__,
- handle, label, error_code, category);
+ AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=0x%x category=%d",
+ __func__, handle, label, error_code, category);
/* map handle to scb */
p_scb = avdt_scb_by_hdl(handle);
@@ -806,7 +773,7 @@
*
******************************************************************************/
uint16_t AVDT_SecurityReq(uint8_t handle, uint8_t* p_data, uint16_t len) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
@@ -845,11 +812,11 @@
******************************************************************************/
uint16_t AVDT_SecurityRsp(uint8_t handle, uint8_t label, uint8_t error_code,
uint8_t* p_data, uint16_t len) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_SUCCESS;
tAVDT_SCB_EVT evt;
- AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=%d len=%d", __func__,
+ AVDT_TRACE_DEBUG("%s: handle=%d label=%d error_code=0x%x len=%d", __func__,
handle, label, error_code, len);
/* map handle to scb */
@@ -910,7 +877,7 @@
******************************************************************************/
uint16_t AVDT_WriteReqOpt(uint8_t handle, BT_HDR* p_pkt, uint32_t time_stamp,
uint8_t m_pt, tAVDT_DATA_OPT_MASK opt) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_SCB_EVT evt;
uint16_t result = AVDT_SUCCESS;
@@ -988,18 +955,19 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t sec_mask,
- tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB* p_ccb = NULL;
+uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t channel_index,
+ uint8_t sec_mask, tAVDT_CTRL_CBACK* p_cback) {
+ AvdtpCcb* p_ccb = NULL;
uint16_t result = AVDT_SUCCESS;
tAVDT_CCB_EVT evt;
- AVDT_TRACE_DEBUG("%s: sec_mask=0x%x", __func__, sec_mask);
+ AVDT_TRACE_WARNING("%s: address=%s channel_index=%d sec_mask=0x%x", __func__,
+ bd_addr.ToString().c_str(), channel_index, sec_mask);
/* find channel control block for this bd addr; if none, allocate one */
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb == NULL) {
- p_ccb = avdt_ccb_alloc(bd_addr);
+ p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
if (p_ccb == NULL) {
/* could not allocate channel control block */
result = AVDT_NO_RESOURCES;
@@ -1018,7 +986,8 @@
avdt_ccb_event(p_ccb, AVDT_CCB_API_CONNECT_REQ_EVT, &evt);
}
- AVDT_TRACE_DEBUG("%s: result=%d", __func__, result);
+ AVDT_TRACE_WARNING("%s: address=%s result=%d", __func__,
+ bd_addr.ToString().c_str(), result);
return result;
}
@@ -1037,7 +1006,7 @@
******************************************************************************/
uint16_t AVDT_DisconnectReq(const RawAddress& bd_addr,
tAVDT_CTRL_CBACK* p_cback) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
uint16_t result = AVDT_SUCCESS;
tAVDT_CCB_EVT evt;
@@ -1071,8 +1040,8 @@
*
******************************************************************************/
uint16_t AVDT_GetL2CapChannel(uint8_t handle) {
- tAVDT_SCB* p_scb;
- tAVDT_CCB* p_ccb;
+ AvdtpScb* p_scb;
+ AvdtpCcb* p_ccb;
uint8_t tcid;
uint16_t lcid = 0;
@@ -1082,7 +1051,7 @@
/* get tcid from type, scb */
tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
}
return (lcid);
@@ -1099,19 +1068,19 @@
*
******************************************************************************/
uint16_t AVDT_GetSignalChannel(uint8_t handle, const RawAddress& bd_addr) {
- tAVDT_SCB* p_scb;
- tAVDT_CCB* p_ccb;
+ AvdtpScb* p_scb;
+ AvdtpCcb* p_ccb;
uint8_t tcid = 0; /* tcid is always 0 for signal channel */
uint16_t lcid = 0;
/* map handle to scb */
if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) &&
((p_ccb = p_scb->p_ccb) != NULL)) {
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
} else {
p_ccb = avdt_ccb_by_bd(bd_addr);
if (p_ccb != NULL) {
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
}
}
@@ -1131,9 +1100,9 @@
******************************************************************************/
uint16_t AVDT_SendReport(uint8_t handle, AVDT_REPORT_TYPE type,
tAVDT_REPORT_DATA* p_data) {
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint16_t result = AVDT_BAD_PARAMS;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
uint8_t *p, *plen, *pm1, *p_end;
uint32_t ssrc;
uint16_t len;
@@ -1142,8 +1111,10 @@
/* map handle to scb && verify parameters */
if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && (p_scb->p_ccb != NULL) &&
- (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) ||
- ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) ||
+ (((type == AVDT_RTCP_PT_SR) &&
+ (p_scb->stream_config.tsep == AVDT_TSEP_SRC)) ||
+ ((type == AVDT_RTCP_PT_RR) &&
+ (p_scb->stream_config.tsep == AVDT_TSEP_SNK)) ||
(type == AVDT_RTCP_PT_SDES))) {
result = AVDT_NO_RESOURCES;
@@ -1234,7 +1205,63 @@
*
*****************************************************************************/
uint8_t AVDT_SetTraceLevel(uint8_t new_level) {
- if (new_level != 0xFF) avdt_cb.trace_level = new_level;
+ if (new_level != 0xFF) avdtp_cb.SetTraceLevel(new_level);
- return (avdt_cb.trace_level);
+ return avdtp_cb.TraceLevel();
+}
+
+void stack_debug_avdtp_api_dump(int fd) {
+ dprintf(fd, "\nAVDTP Stack State:\n");
+ dprintf(fd, " AVDTP signalling L2CAP channel MTU: %d\n",
+ avdtp_cb.rcb.ctrl_mtu);
+ dprintf(fd, " Security mask: 0x%x\n", avdtp_cb.rcb.sec_mask);
+
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ const AvdtpCcb& ccb = avdtp_cb.ccb[i];
+ dprintf(fd, "\n Channel control block: %zu peer: %s\n", i,
+ ccb.peer_addr.ToString().c_str());
+ dprintf(fd, " Allocated: %s\n", ccb.allocated ? "true" : "false");
+ dprintf(fd, " State: %d\n", ccb.state);
+ dprintf(fd, " Link-layer opened: %s\n",
+ ccb.ll_opened ? "true" : "false");
+ dprintf(fd, " Discover in progress: %s\n",
+ ccb.proc_busy ? "true" : "false");
+ dprintf(fd, " Congested: %s\n", ccb.cong ? "true" : "false");
+ dprintf(fd, " Reinitiate connection on idle: %s\n",
+ ccb.reconn ? "true" : "false");
+ dprintf(fd, " Command retransmission count: %d\n", ccb.ret_count);
+ dprintf(fd, " BTA AV SCB index: %d\n", ccb.BtaAvScbIndex());
+
+ for (size_t i = 0; i < AVDT_NUM_SEPS; i++) {
+ const AvdtpScb& scb = ccb.scb[i];
+ dprintf(fd, "\n Stream control block: %zu\n", i);
+ dprintf(fd, " SEP codec: %s\n",
+ A2DP_CodecName(scb.stream_config.cfg.codec_info));
+ dprintf(fd, " SEP type: 0x%x\n", scb.stream_config.tsep);
+ dprintf(fd, " Media type: 0x%x\n", scb.stream_config.media_type);
+ dprintf(fd, " MTU: %d\n", scb.stream_config.mtu);
+ dprintf(fd, " SCB handle: %d\n", scb.ScbHandle());
+ dprintf(fd, " SCB index: %d\n", scb.stream_config.scb_index);
+ dprintf(fd, " Configured codec: %s\n",
+ A2DP_CodecName(scb.curr_cfg.codec_info));
+ dprintf(fd, " Requested codec: %s\n",
+ A2DP_CodecName(scb.req_cfg.codec_info));
+ dprintf(fd, " Transport channel connect timer: %s\n",
+ alarm_is_scheduled(scb.transport_channel_timer)
+ ? "Scheduled"
+ : "Not scheduled");
+ dprintf(fd, " Channel control block peer: %s\n",
+ (scb.p_ccb != nullptr) ? scb.p_ccb->peer_addr.ToString().c_str()
+ : "null");
+ dprintf(fd, " Allocated: %s\n", scb.allocated ? "true" : "false");
+ dprintf(fd, " In use: %s\n", scb.in_use ? "true" : "false");
+ dprintf(fd, " Role: 0x%x\n", scb.role);
+ dprintf(fd, " Remove: %s\n", scb.remove ? "true" : "false");
+ dprintf(fd, " State: %d\n", scb.state);
+ dprintf(fd, " Peer SEID: %d\n", scb.peer_seid);
+ dprintf(fd, " Current event: %d\n", scb.curr_evt);
+ dprintf(fd, " Congested: %s\n", scb.cong ? "true" : "false");
+ dprintf(fd, " Close response code: %d\n", scb.close_code);
+ }
+ }
}
diff --git a/stack/avdt/avdt_ccb.cc b/stack/avdt/avdt_ccb.cc
index bca7aaf..990d0b8 100644
--- a/stack/avdt/avdt_ccb.cc
+++ b/stack/avdt/avdt_ccb.cc
@@ -348,8 +348,10 @@
*
******************************************************************************/
void avdt_ccb_init(void) {
- memset(&avdt_cb.ccb[0], 0, sizeof(tAVDT_CCB) * AVDT_NUM_LINKS);
- avdt_cb.p_ccb_act = avdt_ccb_action;
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ avdtp_cb.ccb[i].Reset(i);
+ }
+ avdtp_cb.p_ccb_act = avdt_ccb_action;
}
/*******************************************************************************
@@ -362,15 +364,15 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_ccb_event(tAVDT_CCB* p_ccb, uint8_t event, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_event(AvdtpCcb* p_ccb, uint8_t event, tAVDT_CCB_EVT* p_data) {
tAVDT_CCB_ST_TBL state_table;
uint8_t action;
int i;
#if (AVDT_DEBUG == TRUE)
- AVDT_TRACE_EVENT("%s: CCB ccb=%d event=%s state=%s", __func__,
+ AVDT_TRACE_EVENT("%s: CCB ccb=%d event=%s state=%s p_ccb=%p", __func__,
avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event],
- avdt_ccb_st_str[p_ccb->state]);
+ avdt_ccb_st_str[p_ccb->state], p_ccb);
#endif
/* look up the state table for the current state */
@@ -388,7 +390,7 @@
avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state],
action);
if (action != AVDT_CCB_IGNORE) {
- (*avdt_cb.p_ccb_act[action])(p_ccb, p_data);
+ (*avdtp_cb.p_ccb_act[action])(p_ccb, p_data);
} else {
break;
}
@@ -405,8 +407,8 @@
* Returns pointer to the ccb, or NULL if none found.
*
******************************************************************************/
-tAVDT_CCB* avdt_ccb_by_bd(const RawAddress& bd_addr) {
- tAVDT_CCB* p_ccb = &avdt_cb.ccb[0];
+AvdtpCcb* avdt_ccb_by_bd(const RawAddress& bd_addr) {
+ AvdtpCcb* p_ccb = &avdtp_cb.ccb[0];
int i;
for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++) {
@@ -435,32 +437,52 @@
* Returns pointer to the ccb, or NULL if none could be allocated.
*
******************************************************************************/
-tAVDT_CCB* avdt_ccb_alloc(const RawAddress& bd_addr) {
- tAVDT_CCB* p_ccb = &avdt_cb.ccb[0];
- int i;
-
- for (i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++) {
+AvdtpCcb* avdt_ccb_alloc(const RawAddress& bd_addr) {
+ // Find available entry
+ AvdtpCcb* p_ccb = &avdtp_cb.ccb[0];
+ for (int i = 0; i < AVDT_NUM_LINKS; i++, p_ccb++) {
if (!p_ccb->allocated) {
- p_ccb->allocated = true;
- p_ccb->peer_addr = bd_addr;
- p_ccb->cmd_q = fixed_queue_new(SIZE_MAX);
- p_ccb->rsp_q = fixed_queue_new(SIZE_MAX);
- p_ccb->idle_ccb_timer = alarm_new("avdt_ccb.idle_ccb_timer");
- p_ccb->ret_ccb_timer = alarm_new("avdt_ccb.ret_ccb_timer");
- p_ccb->rsp_ccb_timer = alarm_new("avdt_ccb.rsp_ccb_timer");
- AVDT_TRACE_DEBUG("avdt_ccb_alloc %d", i);
- break;
+ p_ccb->Allocate(bd_addr);
+ AVDT_TRACE_DEBUG("%s: allocated (index %d)", __func__, i);
+ return p_ccb;
}
}
- if (i == AVDT_NUM_LINKS) {
- /* out of ccbs */
- p_ccb = NULL;
- AVDT_TRACE_WARNING("Out of ccbs");
+ AVDT_TRACE_WARNING("%s: out of AvdtpCcb entries", __func__);
+ return nullptr;
+}
+
+AvdtpCcb* avdt_ccb_alloc_by_channel_index(const RawAddress& bd_addr,
+ uint8_t channel_index) {
+ // Allocate the entry for the specified channel index
+ if (channel_index >= AVDT_NUM_LINKS) {
+ AVDT_TRACE_ERROR("%s: peer %s invalid channel index %d (max %d)", __func__,
+ bd_addr.ToString().c_str(), channel_index, AVDT_NUM_LINKS);
+ return nullptr;
}
+ AvdtpCcb* p_ccb = &avdtp_cb.ccb[channel_index];
+ if (p_ccb->allocated) {
+ AVDT_TRACE_ERROR("%s: peer %s channel index %d already allocated", __func__,
+ bd_addr.ToString().c_str(), channel_index);
+ return nullptr;
+ }
+ p_ccb->Allocate(bd_addr);
+ AVDT_TRACE_DEBUG("%s: allocated (index %d) peer=%s p_ccb=%p", __func__,
+ channel_index, p_ccb->peer_addr.ToString().c_str(), p_ccb);
return p_ccb;
}
+void AvdtpCcb::Allocate(const RawAddress& peer_address) {
+ ResetCcb();
+ peer_addr = peer_address;
+ cmd_q = fixed_queue_new(SIZE_MAX);
+ rsp_q = fixed_queue_new(SIZE_MAX);
+ idle_ccb_timer = alarm_new("avdtp_ccb.idle_ccb_timer");
+ ret_ccb_timer = alarm_new("avdtp_ccb.ret_ccb_timer");
+ rsp_ccb_timer = alarm_new("avdtp_ccb.rsp_ccb_timer");
+ allocated = true;
+}
+
/*******************************************************************************
*
* Function avdt_ccb_dealloc
@@ -471,14 +493,11 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_dealloc(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
- AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d", avdt_ccb_to_idx(p_ccb));
- alarm_free(p_ccb->idle_ccb_timer);
- alarm_free(p_ccb->ret_ccb_timer);
- alarm_free(p_ccb->rsp_ccb_timer);
- fixed_queue_free(p_ccb->cmd_q, NULL);
- fixed_queue_free(p_ccb->rsp_q, NULL);
- memset(p_ccb, 0, sizeof(tAVDT_CCB));
+void avdt_ccb_dealloc(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+ AVDT_TRACE_DEBUG("%s: deallocated (index %d) peer=%s p_ccb=%p", __func__,
+ avdt_ccb_to_idx(p_ccb), p_ccb->peer_addr.ToString().c_str(),
+ p_ccb);
+ p_ccb->ResetCcb();
}
/*******************************************************************************
@@ -491,9 +510,9 @@
* Returns Index of ccb.
*
******************************************************************************/
-uint8_t avdt_ccb_to_idx(tAVDT_CCB* p_ccb) {
+uint8_t avdt_ccb_to_idx(AvdtpCcb* p_ccb) {
/* use array arithmetic to determine index */
- return (uint8_t)(p_ccb - avdt_cb.ccb);
+ return (uint8_t)(p_ccb - avdtp_cb.ccb);
}
/*******************************************************************************
@@ -506,12 +525,12 @@
* Returns pointer to the ccb, or NULL if none found.
*
******************************************************************************/
-tAVDT_CCB* avdt_ccb_by_idx(uint8_t idx) {
- tAVDT_CCB* p_ccb;
+AvdtpCcb* avdt_ccb_by_idx(uint8_t idx) {
+ AvdtpCcb* p_ccb;
/* verify index */
if (idx < AVDT_NUM_LINKS) {
- p_ccb = &avdt_cb.ccb[idx];
+ p_ccb = &avdtp_cb.ccb[idx];
} else {
p_ccb = NULL;
AVDT_TRACE_WARNING("No ccb for idx %d", idx);
diff --git a/stack/avdt/avdt_ccb_act.cc b/stack/avdt/avdt_ccb_act.cc
index 4fdbee0..52f3857 100644
--- a/stack/avdt/avdt_ccb_act.cc
+++ b/stack/avdt/avdt_ccb_act.cc
@@ -46,7 +46,7 @@
* Returns void.
*
******************************************************************************/
-static void avdt_ccb_clear_ccb(tAVDT_CCB* p_ccb) {
+static void avdt_ccb_clear_ccb(AvdtpCcb* p_ccb) {
BT_HDR* p_buf;
/* clear certain ccb variables */
@@ -75,7 +75,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chan_open(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chan_open(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
BTM_SetOutService(p_ccb->peer_addr, BTM_SEC_SERVICE_AVDTP, AVDT_CHAN_SIG);
avdt_ad_open_req(AVDT_CHAN_SIG, p_ccb, NULL, AVDT_INT);
}
@@ -91,7 +91,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chan_close(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chan_close(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
/* close the transport channel used by this CCB */
avdt_ad_close_req(AVDT_CHAN_SIG, p_ccb, NULL);
}
@@ -107,9 +107,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chk_close(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chk_close(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
+ AvdtpScb* p_scb = &(p_ccb->scb[0]);
/* see if there are any active scbs associated with this ccb */
for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
@@ -122,7 +122,7 @@
if (i == AVDT_NUM_SEPS) {
alarm_cancel(p_ccb->ret_ccb_timer);
alarm_cancel(p_ccb->rsp_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.idle_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.idle_tout * 1000;
alarm_set_on_mloop(p_ccb->idle_ccb_timer, interval_ms,
avdt_ccb_idle_ccb_timer_timeout, p_ccb);
}
@@ -141,23 +141,25 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
tAVDT_SEP_INFO sep_info[AVDT_NUM_SEPS];
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
- int i;
+ AvdtpScb* p_scb = &(p_ccb->scb[0]);
+
+ AVDT_TRACE_DEBUG("%s: p_ccb index=%d", __func__, avdt_ccb_to_idx(p_ccb));
p_data->msg.discover_rsp.p_sep_info = sep_info;
p_data->msg.discover_rsp.num_seps = 0;
/* for all allocated scbs */
- for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
+ for (int i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
if (p_scb->allocated) {
/* copy sep info */
sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
- sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+ sep_info[p_data->msg.discover_rsp.num_seps].seid = p_scb->ScbHandle();
sep_info[p_data->msg.discover_rsp.num_seps].media_type =
- p_scb->cs.media_type;
- sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
+ p_scb->stream_config.media_type;
+ sep_info[p_data->msg.discover_rsp.num_seps].tsep =
+ p_scb->stream_config.tsep;
p_data->msg.discover_rsp.num_seps++;
}
@@ -179,13 +181,14 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* we're done with procedure */
p_ccb->proc_busy = false;
/* call app callback with results */
- (*p_ccb->proc_cback)(0, &p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
- (tAVDT_CTRL*)(&p_data->msg.discover_rsp));
+ (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_DISCOVER_CFM_EVT,
+ (tAVDT_CTRL*)(&p_data->msg.discover_rsp),
+ p_ccb->BtaAvScbIndex());
}
/*******************************************************************************
@@ -201,13 +204,13 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
- tAVDT_SCB* p_scb;
+void avdt_ccb_hdl_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
+ AvdtpScb* p_scb;
/* look up scb for seid sent to us */
p_scb = avdt_scb_by_hdl(p_data->msg.single.seid);
- p_data->msg.svccap.p_cfg = &p_scb->cs.cfg;
+ p_data->msg.svccap.p_cfg = &p_scb->stream_config.cfg;
avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data);
}
@@ -224,13 +227,14 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* we're done with procedure */
p_ccb->proc_busy = false;
/* call app callback with results */
- (*p_ccb->proc_cback)(0, &p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT,
- (tAVDT_CTRL*)(&p_data->msg.svccap));
+ (*p_ccb->proc_cback)(0, p_ccb->peer_addr, AVDT_GETCAP_CFM_EVT,
+ (tAVDT_CTRL*)(&p_data->msg.svccap),
+ p_ccb->BtaAvScbIndex());
}
/*******************************************************************************
@@ -246,7 +250,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t err_code = 0;
/* verify all streams in the right state */
@@ -277,11 +281,11 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t event;
int i;
uint8_t* p;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
/* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_START_RSP_EVT
@@ -313,7 +317,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t seid;
uint8_t err_code = 0;
@@ -347,11 +351,11 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_hdl_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t event;
int i;
uint8_t* p;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
/* determine rsp or rej event */
event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_SUSPEND_RSP_EVT
@@ -382,7 +386,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* store info in ccb struct */
p_ccb->p_proc_data = p_data->discover.p_sep_info;
p_ccb->proc_cback = p_data->discover.p_cback;
@@ -407,7 +411,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* send response */
avdt_msg_send_rsp(p_ccb, AVDT_SIG_DISCOVER, &p_data->msg);
}
@@ -425,7 +429,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t sig_id = AVDT_SIG_GETCAP;
/* store info in ccb struct */
@@ -454,7 +458,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
uint8_t sig_id = AVDT_SIG_GETCAP;
if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP)
@@ -477,9 +481,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_MSG avdt_msg;
uint8_t seid_list[AVDT_NUM_SEPS];
@@ -527,8 +531,8 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
- tAVDT_SCB* p_scb;
+void avdt_ccb_snd_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
+ AvdtpScb* p_scb;
int i;
/* send response message */
@@ -557,9 +561,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
tAVDT_MSG avdt_msg;
uint8_t seid_list[AVDT_NUM_SEPS];
@@ -602,8 +606,8 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
- tAVDT_SCB* p_scb;
+void avdt_ccb_snd_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
+ AvdtpScb* p_scb;
int i;
/* send response message */
@@ -632,9 +636,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_clear_cmds(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_clear_cmds(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
int i;
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
+ AvdtpScb* p_scb = &(p_ccb->scb[0]);
uint8_t err_code = AVDT_ERR_CONNECT;
/* clear the ccb */
@@ -675,10 +679,10 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_cmd_fail(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_cmd_fail(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
tAVDT_MSG msg;
uint8_t evt;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
if (p_ccb->p_curr_cmd != NULL) {
/* set up data */
@@ -718,7 +722,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_free_cmd(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_free_cmd(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
osi_free_and_reset((void**)&p_ccb->p_curr_cmd);
}
@@ -733,7 +737,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_cong_state(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_cong_state(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
p_ccb->cong = p_data->llcong;
}
@@ -750,7 +754,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_ret_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_ret_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
p_ccb->ret_count++;
if (p_ccb->ret_count == AVDT_RET_MAX) {
/* command failed */
@@ -776,7 +780,7 @@
/* restart ret timer */
alarm_cancel(p_ccb->idle_ccb_timer);
alarm_cancel(p_ccb->rsp_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
avdt_ccb_ret_ccb_timer_timeout, p_ccb);
}
@@ -793,7 +797,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_cmd(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_cmd(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
BT_HDR* p_msg;
/* do we have commands to send? send next command; make sure we're clear;
@@ -822,7 +826,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_snd_msg(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_snd_msg(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
BT_HDR* p_msg;
/* if not congested */
@@ -858,7 +862,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_set_reconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_set_reconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
p_ccb->reconn = true;
}
@@ -872,7 +876,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_clr_reconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_clr_reconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
p_ccb->reconn = false;
}
@@ -888,7 +892,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chk_reconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chk_reconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
if (p_ccb->reconn) {
p_ccb->reconn = false;
@@ -919,7 +923,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_chk_timer(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_chk_timer(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
alarm_cancel(p_ccb->idle_ccb_timer);
}
@@ -933,7 +937,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_set_conn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_set_conn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/* save callback */
p_ccb->p_conn_cback = p_data->connect.p_cback;
@@ -953,7 +957,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_set_disconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_set_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
/*
AVDT_TRACE_EVENT("avdt_ccb_set_disconn:conn:x%x, api:x%x",
p_ccb->p_conn_cback, p_data->disconnect.p_cback);
@@ -973,7 +977,7 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_do_disconn(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_do_disconn(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
/* clear any pending commands */
avdt_ccb_clear_cmds(p_ccb, NULL);
@@ -991,17 +995,20 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_ll_closed(tAVDT_CCB* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_ll_closed(AvdtpCcb* p_ccb, UNUSED_ATTR tAVDT_CCB_EVT* p_data) {
tAVDT_CTRL_CBACK* p_cback;
tAVDT_CTRL avdt_ctrl;
+ AVDT_TRACE_DEBUG("%s peer %s", __func__, p_ccb->peer_addr.ToString().c_str());
+
/* clear any pending commands */
avdt_ccb_clear_cmds(p_ccb, NULL);
/* save callback pointer, bd addr */
p_cback = p_ccb->p_conn_cback;
- if (!p_cback) p_cback = avdt_cb.p_conn_cback;
+ if (!p_cback) p_cback = avdtp_cb.p_conn_cback;
RawAddress bd_addr = p_ccb->peer_addr;
+ uint8_t bta_av_scb_index = p_ccb->BtaAvScbIndex();
/* dealloc ccb */
avdt_ccb_dealloc(p_ccb, NULL);
@@ -1009,7 +1016,8 @@
/* call callback */
if (p_cback) {
avdt_ctrl.hdr.err_code = 0;
- (*p_cback)(0, &bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl);
+ (*p_cback)(0, bd_addr, AVDT_DISCONNECT_IND_EVT, &avdt_ctrl,
+ bta_av_scb_index);
}
}
@@ -1023,18 +1031,21 @@
* Returns void.
*
******************************************************************************/
-void avdt_ccb_ll_opened(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data) {
+void avdt_ccb_ll_opened(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
+ AVDT_TRACE_DEBUG("%s peer %s BtaAvScbIndex=%d p_ccb=%p", __func__,
+ p_ccb->peer_addr.ToString().c_str(), p_ccb->BtaAvScbIndex(),
+ p_ccb);
p_ccb->ll_opened = true;
- if (!p_ccb->p_conn_cback) p_ccb->p_conn_cback = avdt_cb.p_conn_cback;
+ if (!p_ccb->p_conn_cback) p_ccb->p_conn_cback = avdtp_cb.p_conn_cback;
/* call callback */
if (p_ccb->p_conn_cback) {
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param;
- (*p_ccb->p_conn_cback)(0, &p_ccb->peer_addr, AVDT_CONNECT_IND_EVT,
- &avdt_ctrl);
+ (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT,
+ &avdt_ctrl, p_ccb->BtaAvScbIndex());
}
}
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
index 0a65cfb..1c35448 100644
--- a/stack/avdt/avdt_int.h
+++ b/stack/avdt/avdt_int.h
@@ -304,7 +304,7 @@
/* adaption layer number of stream routing table entries */
/* 2 channels(1 media, 1 report) for each SEP and one for signalling */
-#define AVDT_NUM_RT_TBL ((AVDT_NUM_SEPS << 1) + 1)
+#define AVDT_NUM_RT_TBL (AVDT_NUM_SEPS * AVDT_CHAN_NUM_TYPES + 1)
/* adaption layer number of transport channel table entries - moved to target.h
#define AVDT_NUM_TC_TBL (AVDT_NUM_SEPS + AVDT_NUM_LINKS) */
@@ -320,7 +320,7 @@
#define AVDT_AD_ST_SEC_INT 7 /* Security process as INT */
#define AVDT_AD_ST_SEC_ACP 8 /* Security process as ACP */
-/* Configuration flags. tAVDT_TC_TBL.cfg_flags */
+/* Configuration flags. AvdtpTransportChannel.cfg_flags */
#define AVDT_L2C_CFG_IND_DONE (1 << 0)
#define AVDT_L2C_CFG_CFM_DONE (1 << 1)
#define AVDT_L2C_CFG_CONN_INT (1 << 2)
@@ -360,7 +360,7 @@
typedef struct {
tAVDT_EVT_HDR single;
tAVDT_CTRL_CBACK* p_cback;
- tAVDT_CFG* p_cfg;
+ AvdtpSepConfig* p_cfg;
} tAVDT_CCB_API_GETCAP;
/* data type for AVDT_CCB_API_CONNECT_REQ_EVT */
@@ -383,42 +383,6 @@
uint8_t err_code;
} tAVDT_CCB_EVT;
-/* channel control block type */
-typedef struct {
- RawAddress peer_addr; /* BD address of peer */
- /*
- * NOTE: idle_ccb_timer, ret_ccb_timer and rsp_ccb_timer are mutually
- * exclusive - no more than one timer should be running at the same time.
- */
- alarm_t* idle_ccb_timer; /* Idle CCB timer entry */
- alarm_t* ret_ccb_timer; /* Ret CCB timer entry */
- alarm_t* rsp_ccb_timer; /* Rsp CCB timer entry */
- fixed_queue_t* cmd_q; /* Queue for outgoing command messages */
- fixed_queue_t* rsp_q; /* Queue for outgoing response and reject messages */
- tAVDT_CTRL_CBACK* proc_cback; /* Procedure callback function */
- tAVDT_CTRL_CBACK*
- p_conn_cback; /* Connection/disconnection callback function */
- void* p_proc_data; /* Pointer to data storage for procedure */
- BT_HDR* p_curr_cmd; /* Current command being sent awaiting response */
- BT_HDR* p_curr_msg; /* Current message being sent */
- BT_HDR* p_rx_msg; /* Current message being received */
- bool allocated; /* Whether ccb is allocated */
- uint8_t state; /* The CCB state machine state */
- bool ll_opened; /* true if LL is opened */
- bool proc_busy; /* true when a discover or get capabilities procedure in
- progress */
- uint8_t proc_param; /* Procedure parameter; either SEID for get capabilities
- or number of SEPS for discover */
- bool cong; /* Whether signaling channel is congested */
- uint8_t label; /* Message header "label" (sequence number) */
- bool reconn; /* If true, reinitiate connection after transitioning from
- CLOSING to IDLE state */
- uint8_t ret_count; /* Command retransmission count */
-} tAVDT_CCB;
-
-/* type for action functions */
-typedef void (*tAVDT_CCB_ACTION)(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-
/* type for AVDT_SCB_API_WRITE_REQ_EVT */
typedef struct {
BT_HDR* p_buf;
@@ -445,67 +409,404 @@
BT_HDR* p_pkt;
} tAVDT_SCB_EVT;
-/* stream control block type */
-typedef struct {
- tAVDT_CS cs; /* stream creation struct */
- tAVDT_CFG curr_cfg; /* current configuration */
- tAVDT_CFG req_cfg; /* requested configuration */
- alarm_t* transport_channel_timer; /* transport channel connect timer */
- BT_HDR* p_pkt; /* packet waiting to be sent */
- tAVDT_CCB* p_ccb; /* ccb associated with this scb */
- uint16_t media_seq; /* media packet sequence number */
- bool allocated; /* whether scb is allocated or unused */
- bool in_use; /* whether stream being used by peer */
- uint8_t role; /* initiator/acceptor role in current procedure */
- bool remove; /* whether CB is marked for removal */
- uint8_t state; /* state machine state */
- uint8_t peer_seid; /* SEID of peer stream */
- uint8_t curr_evt; /* current event; set only by state machine */
- bool cong; /* Whether media transport channel is congested */
- uint8_t close_code; /* Error code received in close response */
-} tAVDT_SCB;
+class AvdtpCcb;
-/* type for action functions */
-typedef void (*tAVDT_SCB_ACTION)(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
+/**
+ * AVDTP Stream Control Block.
+ */
+class AvdtpScb {
+ public:
+ AvdtpScb()
+ : transport_channel_timer(nullptr),
+ p_pkt(nullptr),
+ p_ccb(nullptr),
+ media_seq(0),
+ allocated(false),
+ in_use(false),
+ role(0),
+ remove(false),
+ state(0),
+ peer_seid(0),
+ curr_evt(0),
+ cong(false),
+ close_code(0),
+ scb_handle_(0) {}
-/* adaption layer type for transport channel table */
-typedef struct {
- uint16_t peer_mtu; /* L2CAP mtu of the peer device */
- uint16_t my_mtu; /* Our MTU for this channel */
- uint16_t my_flush_to; /* Our flush timeout for this channel */
+ /**
+ * Allocate the entry for usage.
+ * Previous state will be reset and initialized.
+ *
+ * @param p_avdtp_ccb the AvdtCcb entry to use
+ * @param avdtp_stream_config the stream config to use
+ */
+ void Allocate(AvdtpCcb* p_avdtp_ccb,
+ const AvdtpStreamConfig& avdtp_stream_config);
+
+ /**
+ * Recycle the entry by resetting it, mark it as allocated and keeping
+ * the following state:
+ * - stream_config
+ * - p_ccb
+ */
+ void Recycle() {
+ AvdtpStreamConfig stream_config_saved = stream_config;
+ AvdtpCcb* p_ccb_saved = p_ccb;
+ Allocate(p_ccb_saved, stream_config_saved);
+ }
+
+ /**
+ * Reset all the state.
+ *
+ * @param scb_handle the AVDTP SCB handle to use
+ */
+ void Reset(uint8_t scb_handle) {
+ stream_config.Reset();
+ curr_cfg.Reset();
+ req_cfg.Reset();
+
+ alarm_free(transport_channel_timer);
+ transport_channel_timer = nullptr;
+
+ p_pkt = nullptr;
+ p_ccb = nullptr;
+ media_seq = 0;
+ allocated = false;
+ in_use = false;
+ role = 0;
+ remove = false;
+ state = 0;
+ peer_seid = 0;
+ curr_evt = 0;
+ cong = false;
+ close_code = 0;
+ scb_handle_ = scb_handle;
+ }
+
+ /**
+ * Get the AVDTP SCB handle for this entry.
+ */
+ uint8_t ScbHandle() const { return scb_handle_; }
+
+ AvdtpStreamConfig stream_config; // Stream configuration
+ AvdtpSepConfig curr_cfg; // Current configuration
+ AvdtpSepConfig req_cfg; // Requested configuration
+ alarm_t* transport_channel_timer; // Transport channel connect timer
+ BT_HDR* p_pkt; // Packet waiting to be sent
+ AvdtpCcb* p_ccb; // CCB associated with this SCB
+ uint16_t media_seq; // Media packet sequence number
+ bool allocated; // True if the SCB is allocated
+ bool in_use; // True if used by peer
+ uint8_t role; // Initiator/acceptor role in current procedure
+ bool remove; // True if the SCB is marked for removal
+ uint8_t state; // State machine state
+ uint8_t peer_seid; // SEID of peer stream
+ uint8_t curr_evt; // current event; set only by the state machine
+ bool cong; // True if the media transport channel is congested
+ uint8_t close_code; // Error code received in close response
+
+ private:
+ uint8_t scb_handle_; // Unique handle for this AvdtpScb entry
+};
+
+/**
+ * AVDTP Channel Control Block.
+ */
+class AvdtpCcb {
+ public:
+ AvdtpCcb()
+ : peer_addr(RawAddress::kEmpty),
+ scb{},
+ idle_ccb_timer(nullptr),
+ ret_ccb_timer(nullptr),
+ rsp_ccb_timer(nullptr),
+ cmd_q(nullptr),
+ rsp_q(nullptr),
+ proc_cback(nullptr),
+ p_conn_cback(nullptr),
+ p_proc_data(nullptr),
+ p_curr_cmd(nullptr),
+ p_curr_msg(nullptr),
+ p_rx_msg(nullptr),
+ allocated(false),
+ state(0),
+ ll_opened(false),
+ proc_busy(false),
+ proc_param(0),
+ cong(false),
+ label(0),
+ reconn(false),
+ ret_count(0),
+ bta_av_scb_index_(0) {}
+
+ /**
+ * Allocate the entry for usage.
+ *
+ * NOTE: The corresponding AvdtpScb entries are allocated independently.
+ * @param peer_address the peer address
+ */
+ void Allocate(const RawAddress& peer_address);
+
+ /**
+ * Reset all the state.
+ *
+ * @param bta_av_scb_index the BTA AV SCB index to use
+ */
+ void Reset(uint8_t bta_av_scb_index) {
+ bta_av_scb_index_ = bta_av_scb_index;
+ ResetCcb();
+ for (size_t i = 0; i < AVDT_NUM_SEPS; i++) {
+ scb[i].Reset(0);
+ }
+ }
+
+ /**
+ * Reset only the Channel Control Block state without the Stream
+ * Control Block entries. The bta_av_scb_index_ is also preserved.
+ */
+ void ResetCcb() {
+ peer_addr = RawAddress::kEmpty;
+
+ alarm_free(idle_ccb_timer);
+ idle_ccb_timer = nullptr;
+
+ alarm_free(ret_ccb_timer);
+ ret_ccb_timer = nullptr;
+
+ alarm_free(rsp_ccb_timer);
+ rsp_ccb_timer = nullptr;
+
+ fixed_queue_free(cmd_q, nullptr);
+ cmd_q = nullptr;
+
+ fixed_queue_free(rsp_q, nullptr);
+ rsp_q = nullptr;
+
+ proc_cback = nullptr;
+ p_conn_cback = nullptr;
+ p_proc_data = nullptr;
+ p_curr_cmd = nullptr;
+ p_curr_msg = nullptr;
+ p_rx_msg = nullptr;
+ allocated = false;
+ state = 0;
+ ll_opened = false;
+ proc_busy = false;
+ proc_param = 0;
+ cong = false;
+ label = 0;
+ reconn = false;
+ ret_count = 0;
+ }
+
+ /**
+ * Get the corresponding BTA AV stream control block index for this entry.
+ */
+ uint8_t BtaAvScbIndex() const { return bta_av_scb_index_; }
+
+ RawAddress peer_addr; // Bluetooth address of peer
+ AvdtpScb scb[AVDT_NUM_SEPS]; // The AVDTP stream control blocks
+
+ /*
+ * NOTE: idle_ccb_timer, ret_ccb_timer and rsp_ccb_timer are mutually
+ * exclusive - no more than one timer should be running at the same time.
+ */
+ alarm_t* idle_ccb_timer; // Idle CCB timer entry
+ alarm_t* ret_ccb_timer; // Ret CCB timer entry
+ alarm_t* rsp_ccb_timer; // Rsp CCB timer entry
+ fixed_queue_t* cmd_q; // Queue for outgoing command messages
+ fixed_queue_t* rsp_q; // Queue for outgoing response and reject messages
+ tAVDT_CTRL_CBACK* proc_cback; // Procedure callback function
+ tAVDT_CTRL_CBACK* p_conn_cback; // Connection/disconnection callback function
+ void* p_proc_data; // Pointer to data storage for procedure
+ BT_HDR* p_curr_cmd; // Current command being sent awaiting response
+ BT_HDR* p_curr_msg; // Current message being sent
+ BT_HDR* p_rx_msg; // Current message being received
+ bool allocated; // Whether ccb is allocated
+ uint8_t state; // The CCB state machine state
+ bool ll_opened; // True if LL is opened
+ bool proc_busy; // True when a discover or get capabilities procedure in
+ // progress
+ uint8_t proc_param; // Procedure parameter; either SEID for get capabilities
+ // or number of SEPS for discover
+ bool cong; // True if the signaling channel is congested
+ uint8_t label; // Message header "label" (sequence number)
+ bool reconn; // If true, reinitiate connection after transitioning from
+ // CLOSING to IDLE state
+ uint8_t ret_count; // Command retransmission count
+
+ private:
+ // The corresponding BTA AV stream control block index for this entry
+ uint8_t bta_av_scb_index_;
+};
+
+/**
+ * AVDTP transport channel entry.
+ * Used in the transport channel table in the adaptation layer.
+ */
+class AvdtpTransportChannel {
+ public:
+ AvdtpTransportChannel()
+ : peer_mtu(0),
+ my_mtu(0),
+ my_flush_to(0),
+ lcid(0),
+ tcid(0),
+ ccb_idx(0),
+ state(0),
+ cfg_flags(0),
+ id(0) {}
+
+ void Reset() {
+ peer_mtu = 0;
+ my_mtu = 0;
+ my_flush_to = 0;
+ lcid = 0;
+ tcid = 0;
+ ccb_idx = 0;
+ state = 0;
+ cfg_flags = 0;
+ id = 0;
+ }
+
+ uint16_t peer_mtu; // L2CAP MTU of the peer device
+ uint16_t my_mtu; // Our MTU for this channel
+ uint16_t my_flush_to; // Our flush timeout for this channel
uint16_t lcid;
- uint8_t tcid; /* transport channel id */
- uint8_t ccb_idx; /* channel control block associated with this tc */
- uint8_t state; /* transport channel state */
- uint8_t cfg_flags; /* L2CAP configuration flags */
+ uint8_t tcid; // Transport channel ID
+ uint8_t ccb_idx; // Channel control block for with this transport channel
+ uint8_t state; // Transport channel state
+ uint8_t cfg_flags; // L2CAP configuration flags
uint8_t id;
-} tAVDT_TC_TBL;
+};
-/* adaption layer type for stream routing table */
-typedef struct {
- uint16_t lcid; /* L2CAP LCID of the associated transport channel */
- uint8_t scb_hdl; /* stream control block associated with this tc */
-} tAVDT_RT_TBL;
+/**
+ * AVDTP stream routing entry.
+ * Used in the routing table in the adaption layer.
+ */
+class AvdtpRoutingEntry {
+ public:
+ AvdtpRoutingEntry() : lcid(0), scb_hdl(0) {}
-/* adaption layer control block */
-typedef struct {
- tAVDT_RT_TBL rt_tbl[AVDT_NUM_LINKS][AVDT_NUM_RT_TBL];
- tAVDT_TC_TBL tc_tbl[AVDT_NUM_TC_TBL];
- uint8_t lcid_tbl[MAX_L2CAP_CHANNELS]; /* map LCID to tc_tbl index */
-} tAVDT_AD;
+ void Reset() {
+ lcid = 0;
+ scb_hdl = 0;
+ }
-/* Control block for AVDT */
-typedef struct {
- tAVDT_REG rcb; /* registration control block */
- tAVDT_CCB ccb[AVDT_NUM_LINKS]; /* channel control blocks */
- tAVDT_SCB scb[AVDT_NUM_SEPS]; /* stream control blocks */
- tAVDT_AD ad; /* adaption layer control block */
- tAVDTC_CTRL_CBACK* p_conf_cback; /* conformance callback function */
- const tAVDT_CCB_ACTION* p_ccb_act; /* pointer to CCB action functions */
- const tAVDT_SCB_ACTION* p_scb_act; /* pointer to SCB action functions */
- tAVDT_CTRL_CBACK* p_conn_cback; /* connection callback function */
- uint8_t trace_level; /* trace level */
-} tAVDT_CB;
+ uint16_t lcid; // L2CAP LCID of the associated transport channel
+ uint8_t scb_hdl; // Stream control block for this transport channel
+};
+
+/**
+ * AVDTP adaption layer control block.
+ */
+class AvdtpAdaptationLayer {
+ public:
+ AvdtpAdaptationLayer() : lcid_tbl{} {}
+
+ void Reset() {
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ for (size_t j = 0; j < AVDT_NUM_RT_TBL; j++) {
+ rt_tbl[i][j].Reset();
+ }
+ }
+ for (size_t i = 0; i < AVDT_NUM_TC_TBL; i++) {
+ tc_tbl[i].Reset();
+ }
+ memset(lcid_tbl, 0, sizeof(lcid_tbl));
+ }
+
+ /**
+ * Lookup AvdtpScb entry for a transport channel.
+ *
+ * @param tc the transport channel
+ * @return the corresponding AvdtpScb entry or null of the transport
+ * channel is invalid.
+ */
+ AvdtpScb* LookupAvdtpScb(const AvdtpTransportChannel& tc);
+
+ AvdtpRoutingEntry rt_tbl[AVDT_NUM_LINKS][AVDT_NUM_RT_TBL];
+ AvdtpTransportChannel tc_tbl[AVDT_NUM_TC_TBL];
+ uint8_t lcid_tbl[MAX_L2CAP_CHANNELS]; // Map LCID to tc_tbl index
+};
+
+/**
+ * Types for action functions.
+ */
+typedef void (*tAVDT_CCB_ACTION)(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+typedef void (*tAVDT_SCB_ACTION)(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+
+/**
+ * Control block for AVDTP.
+ */
+class AvdtpCb {
+ public:
+ AvdtpCb()
+ : p_conf_cback(nullptr),
+ p_ccb_act(nullptr),
+ p_scb_act(nullptr),
+ p_conn_cback(nullptr),
+ trace_level_(0) {}
+
+ void Reset() {
+ rcb.Reset();
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ ccb[i].Reset(i);
+ }
+ ad.Reset();
+ p_conf_cback = nullptr;
+ p_ccb_act = nullptr;
+ p_scb_act = nullptr;
+ p_conn_cback = nullptr;
+ trace_level_ = 0;
+ }
+
+ AvdtpRcb rcb; // Registration control block
+ AvdtpCcb ccb[AVDT_NUM_LINKS]; // Channel control blocks
+ AvdtpAdaptationLayer ad; // Adaption layer control block
+ tAVDTC_CTRL_CBACK* p_conf_cback; // Conformance callback function
+ const tAVDT_CCB_ACTION* p_ccb_act; // Pointer to CCB action functions
+ const tAVDT_SCB_ACTION* p_scb_act; // Pointer to SCB action functions
+ tAVDT_CTRL_CBACK* p_conn_cback; // Connection callback function
+
+ /**
+ * Compute the SCB handle for a given AvdtpScb entry.
+ *
+ * @param p_scb the entry to use
+ * @return the computed SCB handle or 0 if the entry is invalid.
+ */
+ uint8_t ComputeScbHandle(const AvdtpScb* p_scb) const {
+ uint8_t scb_handle = 0;
+
+ // Find the entry and in the process compute the unique index
+ // TODO: This mechanism is sub-efficient and should be refactored.
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ for (size_t j = 0; j < AVDT_NUM_SEPS; j++) {
+ scb_handle++;
+ if (&ccb[i].scb[j] == p_scb) {
+ return scb_handle;
+ }
+ }
+ }
+ return 0; // Not found
+ }
+
+ /**
+ * Get the current trace level used for logging.
+ *
+ * @return the current trace level
+ */
+ uint8_t TraceLevel() const { return trace_level_; }
+
+ /**
+ * Set the current trace level used for logging.
+ *
+ * @param trace_level the trace level to set. Should be in the range [1, 6].
+ */
+ void SetTraceLevel(uint8_t trace_level) { trace_level_ = trace_level; }
+
+ private:
+ uint8_t trace_level_; /* trace level */
+};
/*****************************************************************************
* function declarations
@@ -513,156 +814,162 @@
/* CCB function declarations */
extern void avdt_ccb_init(void);
-extern void avdt_ccb_event(tAVDT_CCB* p_ccb, uint8_t event,
+extern void avdt_ccb_event(AvdtpCcb* p_ccb, uint8_t event,
tAVDT_CCB_EVT* p_data);
-extern tAVDT_CCB* avdt_ccb_by_bd(const RawAddress& bd_addr);
-extern tAVDT_CCB* avdt_ccb_alloc(const RawAddress& bd_addr);
-extern void avdt_ccb_dealloc(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern uint8_t avdt_ccb_to_idx(tAVDT_CCB* p_ccb);
-extern tAVDT_CCB* avdt_ccb_by_idx(uint8_t idx);
+extern AvdtpCcb* avdt_ccb_by_bd(const RawAddress& bd_addr);
+extern AvdtpCcb* avdt_ccb_alloc(const RawAddress& bd_addr);
+extern AvdtpCcb* avdt_ccb_alloc_by_channel_index(const RawAddress& bd_addr,
+ uint8_t channel_index);
+extern void avdt_ccb_dealloc(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern uint8_t avdt_ccb_to_idx(AvdtpCcb* p_ccb);
+extern AvdtpCcb* avdt_ccb_by_idx(uint8_t idx);
/* CCB action functions */
-extern void avdt_ccb_chan_open(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chan_close(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chk_close(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_discover_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_discover_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_getcap_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_getcap_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_start_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_start_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_suspend_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_suspend_rsp(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_clear_cmds(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_cmd_fail(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_free_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_cong_state(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_ret_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_cmd(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_snd_msg(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_set_reconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_clr_reconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chk_reconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_chk_timer(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_set_conn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_set_disconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_do_disconn(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_ll_closed(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
-extern void avdt_ccb_ll_opened(tAVDT_CCB* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chan_open(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chan_close(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chk_close(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_hdl_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_discover_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_discover_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_getcap_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_getcap_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_start_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_start_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_suspend_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_suspend_rsp(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_clear_cmds(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_cmd_fail(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_free_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_cong_state(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_ret_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_cmd(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_snd_msg(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_set_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_clr_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chk_reconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_chk_timer(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_set_conn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_set_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_do_disconn(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_ll_closed(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
+extern void avdt_ccb_ll_opened(AvdtpCcb* p_ccb, tAVDT_CCB_EVT* p_data);
/* SCB function prototypes */
-extern void avdt_scb_event(tAVDT_SCB* p_scb, uint8_t event,
+extern void avdt_scb_event(AvdtpScb* p_scb, uint8_t event,
tAVDT_SCB_EVT* p_data);
extern void avdt_scb_init(void);
-extern tAVDT_SCB* avdt_scb_alloc(tAVDT_CS* p_cs);
-extern void avdt_scb_dealloc(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern uint8_t avdt_scb_to_hdl(tAVDT_SCB* p_scb);
-extern tAVDT_SCB* avdt_scb_by_hdl(uint8_t hdl);
-extern uint8_t avdt_scb_verify(tAVDT_CCB* p_ccb, uint8_t state, uint8_t* p_seid,
+extern AvdtpScb* avdt_scb_alloc(uint8_t peer_id,
+ const AvdtpStreamConfig& avdtp_stream_config);
+extern void avdt_scb_dealloc(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern uint8_t avdt_scb_to_hdl(AvdtpScb* p_scb);
+extern AvdtpScb* avdt_scb_by_hdl(uint8_t hdl);
+extern uint8_t avdt_scb_verify(AvdtpCcb* p_ccb, uint8_t state, uint8_t* p_seid,
uint16_t num_seid, uint8_t* p_err_code);
extern void avdt_scb_peer_seid_list(tAVDT_MULTI* p_multi);
-extern uint32_t avdt_scb_gen_ssrc(tAVDT_SCB* p_scb);
+extern uint32_t avdt_scb_gen_ssrc(AvdtpScb* p_scb);
/* SCB action functions */
-extern void avdt_scb_hdl_abort_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_abort_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_close_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_getconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_open_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_open_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_open_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_drop_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_security_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_start_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_start_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_suspend_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_suspend_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_delay_rpt_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_delay_rpt_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_delay_rpt_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_open(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_close_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_tc_open_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_hdl_write_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_abort_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_abort_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_close_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_stream_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_getconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_getconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_open_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_open_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_reconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_security_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_setconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_setconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_snd_tc_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_cb_err(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_cong_state(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_rej_state(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_rej_in_use(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_rej_not_in_use(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_set_remove(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_free_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_chk_snd_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_clr_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_transport_channel_timer(tAVDT_SCB* p_scb,
+extern void avdt_scb_hdl_abort_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_abort_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_close_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_getconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_getconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_open_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_open_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_drop_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_reconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_security_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_setconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_setconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_start_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_start_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_suspend_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_suspend_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_delay_rpt_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_delay_rpt_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_delay_rpt_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_open(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_close_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_tc_open_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_hdl_write_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_abort_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_abort_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_close_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_stream_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_getconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_getconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_open_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_reconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_security_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_setconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_setconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_snd_tc_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_cb_err(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_cong_state(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_rej_state(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_rej_in_use(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_rej_not_in_use(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_set_remove(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_free_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_chk_snd_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_clr_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_transport_channel_timer(AvdtpScb* p_scb,
tAVDT_SCB_EVT* p_data);
-extern void avdt_scb_clr_vars(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data);
+extern void avdt_scb_clr_vars(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data);
/* msg function declarations */
-extern bool avdt_msg_send(tAVDT_CCB* p_ccb, BT_HDR* p_msg);
-extern void avdt_msg_send_cmd(tAVDT_CCB* p_ccb, void* p_scb, uint8_t sig_id,
+extern bool avdt_msg_send(AvdtpCcb* p_ccb, BT_HDR* p_msg);
+extern void avdt_msg_send_cmd(AvdtpCcb* p_ccb, void* p_scb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_send_rsp(tAVDT_CCB* p_ccb, uint8_t sig_id,
+extern void avdt_msg_send_rsp(AvdtpCcb* p_ccb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_send_rej(tAVDT_CCB* p_ccb, uint8_t sig_id,
+extern void avdt_msg_send_rej(AvdtpCcb* p_ccb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_send_grej(tAVDT_CCB* p_ccb, uint8_t sig_id,
+extern void avdt_msg_send_grej(AvdtpCcb* p_ccb, uint8_t sig_id,
tAVDT_MSG* p_params);
-extern void avdt_msg_ind(tAVDT_CCB* p_ccb, BT_HDR* p_buf);
+extern void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf);
/* adaption layer function declarations */
extern void avdt_ad_init(void);
-extern uint8_t avdt_ad_type_to_tcid(uint8_t type, tAVDT_SCB* p_scb);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_by_st(uint8_t type, tAVDT_CCB* p_ccb,
- uint8_t state);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_by_lcid(uint16_t lcid);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_alloc(tAVDT_CCB* p_ccb);
-extern uint8_t avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL* p_tbl);
-extern void avdt_ad_tc_close_ind(tAVDT_TC_TBL* p_tbl, uint16_t reason);
-extern void avdt_ad_tc_open_ind(tAVDT_TC_TBL* p_tbl);
-extern void avdt_ad_tc_cong_ind(tAVDT_TC_TBL* p_tbl, bool is_congested);
-extern void avdt_ad_tc_data_ind(tAVDT_TC_TBL* p_tbl, BT_HDR* p_buf);
-extern tAVDT_TC_TBL* avdt_ad_tc_tbl_by_type(uint8_t type, tAVDT_CCB* p_ccb,
- tAVDT_SCB* p_scb);
-extern uint8_t avdt_ad_write_req(uint8_t type, tAVDT_CCB* p_ccb,
- tAVDT_SCB* p_scb, BT_HDR* p_buf);
-extern void avdt_ad_open_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb,
+extern uint8_t avdt_ad_type_to_tcid(uint8_t type, AvdtpScb* p_scb);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_by_st(uint8_t type,
+ AvdtpCcb* p_ccb,
+ uint8_t state);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_by_lcid(uint16_t lcid);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_alloc(AvdtpCcb* p_ccb);
+extern uint8_t avdt_ad_tc_tbl_to_idx(AvdtpTransportChannel* p_tbl);
+extern void avdt_ad_tc_close_ind(AvdtpTransportChannel* p_tbl, uint16_t reason);
+extern void avdt_ad_tc_open_ind(AvdtpTransportChannel* p_tbl);
+extern void avdt_ad_tc_cong_ind(AvdtpTransportChannel* p_tbl,
+ bool is_congested);
+extern void avdt_ad_tc_data_ind(AvdtpTransportChannel* p_tbl, BT_HDR* p_buf);
+extern AvdtpTransportChannel* avdt_ad_tc_tbl_by_type(uint8_t type,
+ AvdtpCcb* p_ccb,
+ AvdtpScb* p_scb);
+extern uint8_t avdt_ad_write_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
+ BT_HDR* p_buf);
+extern void avdt_ad_open_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb,
uint8_t role);
-extern void avdt_ad_close_req(uint8_t type, tAVDT_CCB* p_ccb, tAVDT_SCB* p_scb);
+extern void avdt_ad_close_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb);
extern void avdt_ccb_idle_ccb_timer_timeout(void* data);
extern void avdt_ccb_ret_ccb_timer_timeout(void* data);
@@ -689,7 +996,7 @@
/******************************************************************************
* Main Control Block
******************************************************************************/
-extern tAVDT_CB avdt_cb;
+extern AvdtpCb avdtp_cb;
/* L2CAP callback registration structure */
extern const tL2CAP_APPL_INFO avdt_l2c_appl;
diff --git a/stack/avdt/avdt_l2c.cc b/stack/avdt/avdt_l2c.cc
index 787e302..1489859 100644
--- a/stack/avdt/avdt_l2c.cc
+++ b/stack/avdt/avdt_l2c.cc
@@ -76,9 +76,9 @@
tBT_TRANSPORT transport,
UNUSED_ATTR void* p_ref_data,
uint8_t res) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
tL2CAP_CFG_INFO cfg;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res);
p_ccb = avdt_ccb_by_bd(*bd_addr);
@@ -92,9 +92,9 @@
L2CAP_CONN_OK);
/* store idx in LCID table, store LCID in routing table */
- avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] =
+ avdtp_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] =
avdt_ad_tc_tbl_to_idx(p_tbl);
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
/* transition to configuration state */
p_tbl->state = AVDT_AD_ST_CFG;
@@ -127,9 +127,9 @@
tBT_TRANSPORT trasnport,
UNUSED_ATTR void* p_ref_data,
uint8_t res) {
- tAVDT_CCB* p_ccb = NULL;
+ AvdtpCcb* p_ccb = NULL;
tL2CAP_CFG_INFO cfg;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d", res);
if (bd_addr) p_ccb = avdt_ccb_by_bd(*bd_addr);
@@ -164,8 +164,8 @@
******************************************************************************/
void avdt_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
UNUSED_ATTR uint16_t psm, uint8_t id) {
- tAVDT_CCB* p_ccb;
- tAVDT_TC_TBL* p_tbl = NULL;
+ AvdtpCcb* p_ccb;
+ AvdtpTransportChannel* p_tbl = NULL;
uint16_t result;
tL2CAP_CFG_INFO cfg;
tBTM_STATUS rc;
@@ -181,7 +181,7 @@
} else {
/* allocate and set up entry; first channel is always signaling */
p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
- p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
+ p_tbl->my_mtu = avdtp_cb.rcb.ctrl_mtu;
p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
p_tbl->tcid = AVDT_CHAN_SIG;
p_tbl->lcid = lcid;
@@ -244,9 +244,9 @@
/* if result ok, proceed with connection */
if (result == L2CAP_CONN_OK) {
/* store idx in LCID table, store LCID in routing table */
- avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
+ avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
avdt_ad_tc_tbl_to_idx(p_tbl);
- avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
+ avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
/* transition to configuration state */
p_tbl->state = AVDT_AD_ST_CFG;
@@ -272,9 +272,9 @@
*
******************************************************************************/
void avdt_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
tL2CAP_CFG_INFO cfg;
- tAVDT_CCB* p_ccb;
+ AvdtpCcb* p_ccb;
AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d", lcid,
result);
@@ -345,7 +345,9 @@
*
******************************************************************************/
void avdt_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
+
+ AVDT_TRACE_DEBUG("%s: lcid: %d", __func__, lcid);
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
@@ -384,7 +386,9 @@
*
******************************************************************************/
void avdt_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
+
+ AVDT_TRACE_DEBUG("%s: lcid: %d", __func__, lcid);
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
@@ -395,7 +399,8 @@
} else {
p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
}
- AVDT_TRACE_DEBUG("peer_mtu: %d, lcid: x%x", p_tbl->peer_mtu, lcid);
+ AVDT_TRACE_DEBUG("%s: peer_mtu: %d, lcid: %d", __func__, p_tbl->peer_mtu,
+ lcid);
/* send L2CAP configure response */
memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
@@ -426,7 +431,7 @@
*
******************************************************************************/
void avdt_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d",
lcid, ack_needed);
@@ -453,7 +458,7 @@
*
******************************************************************************/
void avdt_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d", lcid,
result);
@@ -475,7 +480,7 @@
*
******************************************************************************/
void avdt_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
@@ -495,7 +500,7 @@
*
******************************************************************************/
void avdt_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
/* look up info for this channel */
p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index 908b923..618424f 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -271,7 +271,7 @@
* Returns void.
*
******************************************************************************/
-static void avdt_msg_bld_cfg(uint8_t** p, tAVDT_CFG* p_cfg) {
+static void avdt_msg_bld_cfg(uint8_t** p, AvdtpSepConfig* p_cfg) {
uint8_t len;
/* for now, just build media transport, codec, and content protection, and
@@ -467,10 +467,9 @@
*
******************************************************************************/
static void avdt_msg_bld_svccap(uint8_t** p, tAVDT_MSG* p_msg) {
- tAVDT_CFG cfg;
+ AvdtpSepConfig cfg = *p_msg->svccap.p_cfg;
/* make sure the delay report category is not reported */
- memcpy(&cfg, p_msg->svccap.p_cfg, sizeof(tAVDT_CFG));
cfg.psc_mask &= ~AVDT_PSC_DELAY_RPT;
avdt_msg_bld_cfg(p, &cfg);
}
@@ -518,7 +517,7 @@
* in p_elem.
*
******************************************************************************/
-static uint8_t avdt_msg_prs_cfg(tAVDT_CFG* p_cfg, uint8_t* p, uint16_t len,
+static uint8_t avdt_msg_prs_cfg(AvdtpSepConfig* p_cfg, uint8_t* p, uint16_t len,
uint8_t* p_elem, uint8_t sig_id) {
uint8_t* p_end;
uint8_t elem = 0;
@@ -1023,11 +1022,11 @@
* Returns Congested state; true if CCB congested, false if not.
*
******************************************************************************/
-bool avdt_msg_send(tAVDT_CCB* p_ccb, BT_HDR* p_msg) {
+bool avdt_msg_send(AvdtpCcb* p_ccb, BT_HDR* p_msg) {
uint16_t curr_msg_len;
uint8_t pkt_type;
uint8_t hdr_len;
- tAVDT_TC_TBL* p_tbl;
+ AvdtpTransportChannel* p_tbl;
BT_HDR* p_buf;
uint8_t* p;
uint8_t label;
@@ -1119,16 +1118,16 @@
if (msg == AVDT_MSG_TYPE_CMD) {
/* if retransmit timeout set to zero, sig doesn't use retransmit */
if ((sig == AVDT_SIG_DISCOVER) || (sig == AVDT_SIG_GETCAP) ||
- (sig == AVDT_SIG_SECURITY) || (avdt_cb.rcb.ret_tout == 0)) {
+ (sig == AVDT_SIG_SECURITY) || (avdtp_cb.rcb.ret_tout == 0)) {
alarm_cancel(p_ccb->idle_ccb_timer);
alarm_cancel(p_ccb->ret_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.sig_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.sig_tout * 1000;
alarm_set_on_mloop(p_ccb->rsp_ccb_timer, interval_ms,
avdt_ccb_rsp_ccb_timer_timeout, p_ccb);
} else if (sig != AVDT_SIG_DELAY_RPT) {
alarm_cancel(p_ccb->idle_ccb_timer);
alarm_cancel(p_ccb->rsp_ccb_timer);
- period_ms_t interval_ms = avdt_cb.rcb.ret_tout * 1000;
+ period_ms_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
avdt_ccb_ret_ccb_timer_timeout, p_ccb);
}
@@ -1171,7 +1170,7 @@
* available.
*
******************************************************************************/
-BT_HDR* avdt_msg_asmbl(tAVDT_CCB* p_ccb, BT_HDR* p_buf) {
+BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
uint8_t* p;
uint8_t pkt_type;
BT_HDR* p_ret;
@@ -1292,7 +1291,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_cmd(tAVDT_CCB* p_ccb, void* p_scb, uint8_t sig_id,
+void avdt_msg_send_cmd(AvdtpCcb* p_ccb, void* p_scb, uint8_t sig_id,
tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
@@ -1318,7 +1317,7 @@
}
/* for all others, p_scb points to scb as usual */
else {
- *p = avdt_scb_to_hdl((tAVDT_SCB*)p_scb);
+ *p = avdt_scb_to_hdl((AvdtpScb*)p_scb);
}
}
@@ -1349,7 +1348,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_rsp(tAVDT_CCB* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
+void avdt_msg_send_rsp(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
@@ -1389,7 +1388,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_rej(tAVDT_CCB* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
+void avdt_msg_send_rej(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
@@ -1440,7 +1439,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_send_grej(tAVDT_CCB* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
+void avdt_msg_send_grej(AvdtpCcb* p_ccb, uint8_t sig_id, tAVDT_MSG* p_params) {
uint8_t* p;
uint8_t* p_start;
BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVDT_CMD_BUF_SIZE);
@@ -1476,8 +1475,8 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_msg_ind(tAVDT_CCB* p_ccb, BT_HDR* p_buf) {
- tAVDT_SCB* p_scb;
+void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
+ AvdtpScb* p_scb;
uint8_t* p;
bool ok = true;
bool handle_rsp = false;
@@ -1487,7 +1486,7 @@
uint8_t msg_type;
uint8_t sig = 0;
tAVDT_MSG msg;
- tAVDT_CFG cfg;
+ AvdtpSepConfig cfg;
uint8_t err;
uint8_t evt = 0;
uint8_t scb_hdl;
@@ -1552,7 +1551,7 @@
} else if ((msg_type == AVDT_MSG_TYPE_RSP) &&
((sig == AVDT_SIG_GETCAP) || (sig == AVDT_SIG_GET_ALLCAP))) {
/* parse discover rsp message to struct supplied by app */
- msg.svccap.p_cfg = (tAVDT_CFG*)p_ccb->p_proc_data;
+ msg.svccap.p_cfg = (AvdtpSepConfig*)p_ccb->p_proc_data;
} else if ((msg_type == AVDT_MSG_TYPE_RSP) && (sig == AVDT_SIG_GETCONFIG)) {
/* parse get config rsp message to struct allocated locally */
msg.svccap.p_cfg = &cfg;
diff --git a/stack/avdt/avdt_scb.cc b/stack/avdt/avdt_scb.cc
index c0772f1..eacdf83 100644
--- a/stack/avdt/avdt_scb.cc
+++ b/stack/avdt/avdt_scb.cc
@@ -755,15 +755,16 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_event(tAVDT_SCB* p_scb, uint8_t event, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_event(AvdtpScb* p_scb, uint8_t event, tAVDT_SCB_EVT* p_data) {
tAVDT_SCB_ST_TBL state_table;
uint8_t action;
int i;
#if (AVDT_DEBUG == TRUE)
- AVDT_TRACE_EVENT("%s: SCB hdl=%d event=%d/%s state=%s", __func__,
- avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event],
- avdt_scb_st_str[p_scb->state]);
+ AVDT_TRACE_EVENT(
+ "%s: SCB hdl=%d event=%d/%s state=%s p_avdt_scb=%p scb_index=%d",
+ __func__, avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event],
+ avdt_scb_st_str[p_scb->state], p_scb, p_scb->stream_config.scb_index);
#endif
/* set current event */
p_scb->curr_evt = event;
@@ -780,7 +781,7 @@
for (i = 0; i < AVDT_SCB_ACTIONS; i++) {
action = state_table[event][i];
if (action != AVDT_SCB_IGNORE) {
- (*avdt_cb.p_scb_act[action])(p_scb, p_data);
+ (*avdtp_cb.p_scb_act[action])(p_scb, p_data);
} else {
break;
}
@@ -798,8 +799,13 @@
*
******************************************************************************/
void avdt_scb_init(void) {
- memset(avdt_cb.scb, 0, sizeof(tAVDT_SCB) * AVDT_NUM_SEPS);
- avdt_cb.p_scb_act = avdt_scb_action;
+ for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
+ for (size_t j = 0; j < AVDT_NUM_SEPS; j++) {
+ avdtp_cb.ccb[i].scb[j].Reset(0);
+ }
+ }
+
+ avdtp_cb.p_scb_act = avdt_scb_action;
}
/*******************************************************************************
@@ -812,33 +818,34 @@
* Returns pointer to the scb, or NULL if none could be allocated.
*
******************************************************************************/
-tAVDT_SCB* avdt_scb_alloc(tAVDT_CS* p_cs) {
- tAVDT_SCB* p_scb = &avdt_cb.scb[0];
- int i;
+AvdtpScb* avdt_scb_alloc(uint8_t peer_id,
+ const AvdtpStreamConfig& avdtp_stream_config) {
+ CHECK(peer_id < AVDT_NUM_LINKS);
- /* find available scb */
- for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
+ // Find available entry
+ AvdtpScb* p_scb = &avdtp_cb.ccb[peer_id].scb[0];
+ for (int i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) {
if (!p_scb->allocated) {
- memset(p_scb, 0, sizeof(tAVDT_SCB));
- p_scb->allocated = true;
- p_scb->p_ccb = NULL;
-
- memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS));
- p_scb->transport_channel_timer =
- alarm_new("avdt_scb.transport_channel_timer");
- AVDT_TRACE_DEBUG("%s: hdl=%d, psc_mask:0x%x", __func__, i + 1,
- p_cs->cfg.psc_mask);
- break;
+ p_scb->Allocate(&avdtp_cb.ccb[peer_id], avdtp_stream_config);
+ AVDT_TRACE_DEBUG("%s: allocated (handle=%d, psc_mask:0x%x)", __func__,
+ p_scb->ScbHandle(), avdtp_stream_config.cfg.psc_mask);
+ return p_scb;
}
}
- if (i == AVDT_NUM_SEPS) {
- /* out of ccbs */
- p_scb = NULL;
- AVDT_TRACE_WARNING("Out of scbs");
- }
+ AVDT_TRACE_WARNING("%s: out of AvdtScb entries for peer_id %d", __func__,
+ peer_id);
+ return nullptr;
+}
- return p_scb;
+void AvdtpScb::Allocate(AvdtpCcb* p_avdtp_ccb,
+ const AvdtpStreamConfig& avdtp_stream_config) {
+ uint8_t scb_handle = avdtp_cb.ComputeScbHandle(this);
+ Reset(scb_handle);
+ p_ccb = p_avdtp_ccb;
+ stream_config = avdtp_stream_config;
+ transport_channel_timer = alarm_new("avdtp_scb.transport_channel_timer");
+ allocated = true;
}
/*******************************************************************************
@@ -851,10 +858,9 @@
* Returns void.
*
******************************************************************************/
-void avdt_scb_dealloc(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_dealloc(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
AVDT_TRACE_DEBUG("%s: hdl=%d", __func__, avdt_scb_to_hdl(p_scb));
- alarm_free(p_scb->transport_channel_timer);
- memset(p_scb, 0, sizeof(tAVDT_SCB));
+ p_scb->Recycle();
}
/*******************************************************************************
@@ -867,9 +873,7 @@
* Returns Index of scb.
*
******************************************************************************/
-uint8_t avdt_scb_to_hdl(tAVDT_SCB* p_scb) {
- return (uint8_t)(p_scb - avdt_cb.scb + 1);
-}
+uint8_t avdt_scb_to_hdl(AvdtpScb* p_scb) { return p_scb->ScbHandle(); }
/*******************************************************************************
*
@@ -882,22 +886,26 @@
* is not allocated.
*
******************************************************************************/
-tAVDT_SCB* avdt_scb_by_hdl(uint8_t hdl) {
- tAVDT_SCB* p_scb;
-
- /* verify index */
- if ((hdl > 0) && (hdl <= AVDT_NUM_SEPS)) {
- p_scb = &avdt_cb.scb[hdl - 1];
-
- /* verify scb is allocated */
- if (!p_scb->allocated) {
- p_scb = NULL;
- AVDT_TRACE_WARNING("scb hdl %d not allocated", hdl);
- }
- } else {
- p_scb = NULL;
- AVDT_TRACE_WARNING("scb hdl %d out of range", hdl);
+AvdtpScb* avdt_scb_by_hdl(uint8_t hdl) {
+ // Verify the index
+ if ((hdl < 1) || (hdl > AVDT_NUM_LINKS * AVDT_NUM_SEPS)) {
+ AVDT_TRACE_WARNING("%s: SCB handle %d out of range", __func__, hdl);
+ return nullptr;
}
+
+ uint8_t index = hdl - 1;
+ size_t i = index / AVDT_NUM_LINKS;
+ size_t j = index % AVDT_NUM_SEPS;
+
+ AvdtpScb* p_scb = &avdtp_cb.ccb[i].scb[j];
+ // Verify the whether the scb is allocated
+ if (!p_scb->allocated) {
+ AVDT_TRACE_WARNING("%s: SCB handle %d not allocated", __func__, hdl);
+ return nullptr;
+ }
+
+ AVDT_TRACE_DEBUG("%s: SCB for handle %d found: p_scb=%p scb_index=%d",
+ __func__, hdl, p_scb, p_scb->stream_config.scb_index);
return p_scb;
}
@@ -911,10 +919,10 @@
* Returns SEID that failed, or 0 if success.
*
******************************************************************************/
-uint8_t avdt_scb_verify(tAVDT_CCB* p_ccb, uint8_t state, uint8_t* p_seid,
+uint8_t avdt_scb_verify(AvdtpCcb* p_ccb, uint8_t state, uint8_t* p_seid,
uint16_t num_seid, uint8_t* p_err_code) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
uint8_t nsc_mask;
uint8_t ret = 0;
@@ -922,7 +930,9 @@
/* set nonsupported command mask */
/* translate public state into private state */
nsc_mask = 0;
- if (state == AVDT_VERIFY_SUSPEND) nsc_mask = AVDT_NSC_SUSPEND;
+ if (state == AVDT_VERIFY_SUSPEND) {
+ nsc_mask = AvdtpStreamConfig::AVDT_NSC_SUSPEND;
+ }
/* verify every scb */
for (i = 0, *p_err_code = 0;
@@ -932,7 +942,7 @@
*p_err_code = AVDT_ERR_BAD_STATE;
else if (p_scb->p_ccb != p_ccb)
*p_err_code = AVDT_ERR_BAD_STATE;
- else if (p_scb->cs.nsc_mask & nsc_mask)
+ else if (p_scb->stream_config.nsc_mask & nsc_mask)
*p_err_code = AVDT_ERR_NSC;
switch (state) {
@@ -971,7 +981,7 @@
******************************************************************************/
void avdt_scb_peer_seid_list(tAVDT_MULTI* p_multi) {
int i;
- tAVDT_SCB* p_scb;
+ AvdtpScb* p_scb;
for (i = 0; i < p_multi->num_seps; i++) {
p_scb = avdt_scb_by_hdl(p_multi->seid_list[i]);
diff --git a/stack/avdt/avdt_scb_act.cc b/stack/avdt/avdt_scb_act.cc
index 826e4b9..824dbcb 100644
--- a/stack/avdt/avdt_scb_act.cc
+++ b/stack/avdt/avdt_scb_act.cc
@@ -62,10 +62,10 @@
* Returns SSRC value.
*
******************************************************************************/
-uint32_t avdt_scb_gen_ssrc(tAVDT_SCB* p_scb) {
+uint32_t avdt_scb_gen_ssrc(AvdtpScb* p_scb) {
/* combine the value of the media type and codec type of the SCB */
- return (
- (uint32_t)(p_scb->cs.cfg.codec_info[1] | p_scb->cs.cfg.codec_info[2]));
+ return ((uint32_t)(p_scb->stream_config.cfg.codec_info[1] |
+ p_scb->stream_config.cfg.codec_info[2]));
}
/*******************************************************************************
@@ -78,7 +78,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_abort_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_abort_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->role = AVDT_CLOSE_ACP;
avdt_scb_event(p_scb, AVDT_SCB_API_ABORT_RSP_EVT, p_data);
}
@@ -93,7 +93,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_abort_rsp(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_hdl_abort_rsp(UNUSED_ATTR AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
return;
}
@@ -108,7 +108,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_close_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_close_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->role = AVDT_CLOSE_ACP;
avdt_scb_event(p_scb, AVDT_SCB_API_CLOSE_RSP_EVT, p_data);
}
@@ -123,7 +123,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->close_code = p_data->msg.hdr.err_code;
}
@@ -138,7 +138,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_getconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_getconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.svccap.p_cfg = &p_scb->curr_cfg;
avdt_scb_event(p_scb, AVDT_SCB_API_GETCONFIG_RSP_EVT, p_data);
@@ -154,7 +154,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_getconfig_rsp(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_hdl_getconfig_rsp(UNUSED_ATTR AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
return;
}
@@ -169,7 +169,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_open_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_open_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_scb_event(p_scb, AVDT_SCB_API_OPEN_RSP_EVT, p_data);
}
@@ -185,7 +185,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_open_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_open_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* do exactly same as setconfig reject */
avdt_scb_hdl_setconfig_rej(p_scb, p_data);
}
@@ -200,8 +200,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_open_rsp(tAVDT_SCB* p_scb,
- UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_open_rsp(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
/* initiate opening of trans channels for this SEID */
p_scb->role = AVDT_OPEN_INT;
avdt_ad_open_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, AVDT_INT);
@@ -221,7 +220,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t *p, *p_start;
uint8_t o_v, o_p, o_x, o_cc;
uint8_t m_pt;
@@ -271,12 +270,12 @@
p_data->p_pkt->len -= (offset + pad_len);
p_data->p_pkt->offset += offset;
- if (p_scb->cs.p_sink_data_cback != NULL) {
+ if (p_scb->stream_config.p_sink_data_cback != NULL) {
/* report sequence number */
p_data->p_pkt->layer_specific = seq;
- (*p_scb->cs.p_sink_data_cback)(avdt_scb_to_hdl(p_scb), p_data->p_pkt,
- time_stamp,
- (uint8_t)(m_pt | (marker << 7)));
+ (*p_scb->stream_config.p_sink_data_cback)(
+ avdt_scb_to_hdl(p_scb), p_data->p_pkt, time_stamp,
+ (uint8_t)(m_pt | (marker << 7)));
} else {
osi_free_and_reset((void**)&p_data->p_pkt);
}
@@ -292,7 +291,7 @@
* Returns Nothing.
*
******************************************************************************/
-uint8_t* avdt_scb_hdl_report(tAVDT_SCB* p_scb, uint8_t* p, uint16_t len) {
+uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) {
uint16_t result = AVDT_SUCCESS;
uint8_t* p_start = p;
uint32_t ssrc;
@@ -301,7 +300,7 @@
tAVDT_REPORT_DATA report;
AVDT_TRACE_DEBUG("%s", __func__);
- if (p_scb->cs.p_report_cback) {
+ if (p_scb->stream_config.p_report_cback) {
/* parse report packet header */
AVDT_MSG_PRS_RPT_OCTET1(p, o_v, o_p, o_cc);
pt = *p++;
@@ -351,7 +350,8 @@
}
if (result == AVDT_SUCCESS)
- (*p_scb->cs.p_report_cback)(avdt_scb_to_hdl(p_scb), pt, &report);
+ (*p_scb->stream_config.p_report_cback)(avdt_scb_to_hdl(p_scb), pt,
+ &report);
}
p_start += len;
return p_start;
@@ -366,7 +366,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->p_pkt->layer_specific == AVDT_CHAN_REPORT) {
uint8_t* p = (uint8_t*)(p_data->p_pkt + 1) + p_data->p_pkt->offset;
avdt_scb_hdl_report(p_scb, p, p_data->p_pkt->len);
@@ -386,7 +386,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_drop_pkt(UNUSED_ATTR tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_drop_pkt(UNUSED_ATTR AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
AVDT_TRACE_ERROR("%s dropped incoming media packet", __func__);
osi_free_and_reset((void**)&p_data->p_pkt);
}
@@ -401,21 +401,21 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_reconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_reconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* if command not supported */
- if (p_scb->cs.nsc_mask & AVDT_NSC_RECONFIG) {
+ if (p_scb->stream_config.nsc_mask & AvdtpStreamConfig::AVDT_NSC_RECONFIG) {
/* send reject */
p_data->msg.hdr.err_code = AVDT_ERR_NSC;
p_data->msg.hdr.err_param = 0;
avdt_scb_event(p_scb, AVDT_SCB_API_RECONFIG_RSP_EVT, p_data);
} else {
/* store requested configuration */
- memcpy(&p_scb->req_cfg, p_data->msg.reconfig_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_scb->req_cfg = *p_data->msg.reconfig_cmd.p_cfg;
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- AVDT_RECONFIG_IND_EVT,
- (tAVDT_CTRL*)&p_data->msg.reconfig_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_RECONFIG_IND_EVT,
+ (tAVDT_CTRL*)&p_data->msg.reconfig_cmd, p_scb->stream_config.scb_index);
}
}
@@ -429,7 +429,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->msg.hdr.err_code == 0) {
/* store new configuration */
if (p_scb->req_cfg.num_codec > 0) {
@@ -447,8 +447,9 @@
p_data->msg.svccap.p_cfg = &p_scb->curr_cfg;
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_RECONFIG_CFM_EVT,
- (tAVDT_CTRL*)&p_data->msg.svccap);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_RECONFIG_CFM_EVT,
+ (tAVDT_CTRL*)&p_data->msg.svccap, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -461,17 +462,17 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_security_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_security_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* if command not supported */
- if (p_scb->cs.nsc_mask & AVDT_NSC_SECURITY) {
+ if (p_scb->stream_config.nsc_mask & AvdtpStreamConfig::AVDT_NSC_SECURITY) {
/* send reject */
p_data->msg.hdr.err_code = AVDT_ERR_NSC;
avdt_scb_event(p_scb, AVDT_SCB_API_SECURITY_RSP_EVT, p_data);
} else {
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- AVDT_SECURITY_IND_EVT,
- (tAVDT_CTRL*)&p_data->msg.security_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_SECURITY_IND_EVT,
+ (tAVDT_CTRL*)&p_data->msg.security_cmd, p_scb->stream_config.scb_index);
}
}
@@ -485,10 +486,11 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_SECURITY_CFM_EVT,
- (tAVDT_CTRL*)&p_data->msg.security_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_SECURITY_CFM_EVT,
+ (tAVDT_CTRL*)&p_data->msg.security_cmd, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -502,30 +504,40 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- tAVDT_CFG* p_cfg;
-
- AVDT_TRACE_DEBUG("%s: p_scb->in_use=%d", __func__, p_scb->in_use);
+void avdt_scb_hdl_setconfig_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ AVDT_TRACE_DEBUG("%s: p_scb->in_use=%d p_avdt_scb=%p scb_index=%d", __func__,
+ p_scb->in_use, p_scb, p_scb->stream_config.scb_index);
if (!p_scb->in_use) {
- A2DP_DumpCodecInfo(p_scb->cs.cfg.codec_info);
+ A2DP_DumpCodecInfo(p_scb->stream_config.cfg.codec_info);
A2DP_DumpCodecInfo(p_data->msg.config_cmd.p_cfg->codec_info);
- p_cfg = p_data->msg.config_cmd.p_cfg;
- if (A2DP_GetCodecType(p_scb->cs.cfg.codec_info) ==
+ AvdtpSepConfig* p_cfg = p_data->msg.config_cmd.p_cfg;
+ if (A2DP_GetCodecType(p_scb->stream_config.cfg.codec_info) ==
A2DP_GetCodecType(p_cfg->codec_info)) {
+ /* copy info to scb */
+ AvdtpCcb* p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+ if (p_scb->p_ccb != p_ccb) {
+ AVDT_TRACE_ERROR(
+ "%s: mismatch in AVDTP SCB/CCB state: (p_scb->p_ccb=%p != "
+ "p_ccb=%p): "
+ "p_scb=%p scb_handle=%d ccb_idx=%d",
+ __func__, p_scb->p_ccb, p_ccb, p_scb, p_scb->ScbHandle(),
+ p_data->msg.config_cmd.hdr.ccb_idx);
+ avdt_scb_rej_not_in_use(p_scb, p_data);
+ return;
+ }
/* set sep as in use */
p_scb->in_use = true;
- /* copy info to scb */
- p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
p_scb->peer_seid = p_data->msg.config_cmd.int_seid;
- memcpy(&p_scb->req_cfg, p_cfg, sizeof(tAVDT_CFG));
+ p_scb->req_cfg = *p_cfg;
/* call app callback */
/* handle of scb- which is same as sep handle of bta_av_cb.p_scb*/
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_CONFIG_IND_EVT,
- (tAVDT_CTRL*)&p_data->msg.config_cmd);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_CONFIG_IND_EVT, (tAVDT_CTRL*)&p_data->msg.config_cmd,
+ p_scb->stream_config.scb_index);
} else {
p_data->msg.hdr.err_code = AVDT_ERR_UNSUP_CFG;
p_data->msg.hdr.err_param = 0;
@@ -549,7 +561,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* clear scb variables */
avdt_scb_clr_vars(p_scb, p_data);
@@ -558,8 +570,9 @@
AVDT_CCB_UL_CLOSE_EVT, NULL);
/* call application callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_OPEN_CFM_EVT,
- (tAVDT_CTRL*)&p_data->msg.hdr);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_OPEN_CFM_EVT,
+ (tAVDT_CTRL*)&p_data->msg.hdr, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -572,13 +585,13 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_setconfig_rsp(tAVDT_SCB* p_scb,
+void avdt_scb_hdl_setconfig_rsp(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR single;
if (p_scb->p_ccb != NULL) {
/* save configuration */
- memcpy(&p_scb->curr_cfg, &p_scb->req_cfg, sizeof(tAVDT_CFG));
+ p_scb->curr_cfg = p_scb->req_cfg;
/* initiate open */
single.seid = p_scb->peer_seid;
@@ -598,11 +611,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_start_cmd(tAVDT_SCB* p_scb,
+void avdt_scb_hdl_start_cmd(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_START_IND_EVT, NULL);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_START_IND_EVT, NULL, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -615,10 +629,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_start_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_START_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_start_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_START_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -631,11 +647,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_suspend_cmd(tAVDT_SCB* p_scb,
+void avdt_scb_hdl_suspend_cmd(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_SUSPEND_IND_EVT, NULL);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_SUSPEND_IND_EVT, NULL, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -648,10 +665,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_suspend_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(
- avdt_scb_to_hdl(p_scb), p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_SUSPEND_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_suspend_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_SUSPEND_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -670,13 +689,14 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t hdl = avdt_scb_to_hdl(p_scb);
- tAVDT_CTRL_CBACK* p_ctrl_cback = p_scb->cs.p_ctrl_cback;
+ tAVDT_CTRL_CBACK* p_avdt_ctrl_cback = p_scb->stream_config.p_avdt_ctrl_cback;
tAVDT_CTRL avdt_ctrl;
uint8_t event;
- tAVDT_CCB* p_ccb = p_scb->p_ccb;
+ AvdtpCcb* p_ccb = p_scb->p_ccb;
RawAddress remote_addr = p_ccb->peer_addr;
+ uint8_t scb_index = p_scb->stream_config.scb_index;
/* set up hdr */
avdt_ctrl.hdr.err_code = p_scb->close_code;
@@ -704,7 +724,7 @@
}
/* call app callback */
- (*p_ctrl_cback)(hdl, &remote_addr, event, &avdt_ctrl);
+ (*p_avdt_ctrl_cback)(hdl, remote_addr, event, &avdt_ctrl, scb_index);
}
/*******************************************************************************
@@ -717,7 +737,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_delay_rpt_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_delay_rpt_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_DELAY_RPT,
(tAVDT_MSG*)&p_data->apidelay);
}
@@ -732,10 +752,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_delay_rpt_cmd(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(
- avdt_scb_to_hdl(p_scb), p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_DELAY_REPORT_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_delay_rpt_cmd(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_DELAY_REPORT_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
if (p_scb->p_ccb)
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_DELAY_RPT, &p_data->msg);
@@ -753,10 +775,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_delay_rpt_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- (*p_scb->cs.p_ctrl_cback)(
- avdt_scb_to_hdl(p_scb), p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_DELAY_REPORT_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr);
+void avdt_scb_hdl_delay_rpt_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_DELAY_REPORT_CFM_EVT, (tAVDT_CTRL*)&p_data->msg.hdr,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -769,7 +793,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_close_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_close_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* AVDT_CHAN_SIG does not visit this action */
if (p_data && p_data->close.type != AVDT_CHAN_MEDIA) {
@@ -779,9 +803,10 @@
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = 0;
/* call app callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_REPORT_DISCONN_EVT, &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_REPORT_DISCONN_EVT, &avdt_ctrl, p_scb->stream_config.scb_index);
}
} else {
/* must be in OPEN state. need to go back to idle */
@@ -802,7 +827,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_open(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_open(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t event;
uint8_t role;
@@ -812,8 +837,8 @@
(p_scb->role == AVDT_OPEN_INT) ? AVDT_OPEN_CFM_EVT : AVDT_OPEN_IND_EVT;
p_data->open.hdr.err_code = 0;
- AVDT_TRACE_DEBUG("psc_mask: cfg: 0x%x, req:0x%x, cur: 0x%x",
- p_scb->cs.cfg.psc_mask, p_scb->req_cfg.psc_mask,
+ AVDT_TRACE_DEBUG("%s: psc_mask: cfg: 0x%x, req:0x%x, cur: 0x%x", __func__,
+ p_scb->stream_config.cfg.psc_mask, p_scb->req_cfg.psc_mask,
p_scb->curr_cfg.psc_mask);
if (p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT) {
/* open the reporting channel, if both devices support it */
@@ -822,9 +847,10 @@
}
/* call app callback */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- event, (tAVDT_CTRL*)&p_data->open);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty, event,
+ (tAVDT_CTRL*)&p_data->open, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -839,7 +865,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_tc_open_sto(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_tc_open_sto(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* open reporting channel here, when it is implemented */
@@ -847,9 +873,10 @@
if (p_data->open.hdr.err_code == AVDT_CHAN_REPORT) {
avdt_ctrl.hdr.err_code = 0;
avdt_ctrl.hdr.err_param = 1;
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
- p_scb->p_ccb ? &p_scb->p_ccb->peer_addr : NULL,
- AVDT_REPORT_CONN_EVT, &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb),
+ p_scb->p_ccb ? p_scb->p_ccb->peer_addr : RawAddress::kEmpty,
+ AVDT_REPORT_CONN_EVT, &avdt_ctrl, p_scb->stream_config.scb_index);
}
}
@@ -864,7 +891,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_hdl_write_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_hdl_write_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
uint8_t* p;
uint32_t ssrc;
bool add_rtp_header = !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP);
@@ -912,7 +939,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_abort_req(tAVDT_SCB* p_scb,
+void avdt_scb_snd_abort_req(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
@@ -938,7 +965,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_abort_rsp(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_snd_abort_rsp(UNUSED_ATTR AvdtpScb* p_scb,
tAVDT_SCB_EVT* p_data) {
avdt_msg_send_rsp(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx), AVDT_SIG_ABORT,
&p_data->msg);
@@ -953,7 +980,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_close_req(tAVDT_SCB* p_scb,
+void avdt_scb_snd_close_req(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
@@ -975,7 +1002,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_stream_close(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_stream_close(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
osi_free_and_reset((void**)&p_scb->p_pkt);
avdt_scb_snd_close_req(p_scb, p_data);
}
@@ -989,7 +1016,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_close_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_close_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_CLOSE, &p_data->msg);
}
@@ -1002,7 +1029,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_getconfig_req(tAVDT_SCB* p_scb,
+void avdt_scb_snd_getconfig_req(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
@@ -1022,7 +1049,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_getconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_getconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_GETCONFIG, &p_data->msg);
}
@@ -1035,8 +1062,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_open_req(tAVDT_SCB* p_scb,
- UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_open_req(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_EVT_HDR hdr;
hdr.seid = p_scb->peer_seid;
@@ -1057,7 +1083,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_open_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_open_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
/* notify adaption that we're waiting for transport channel open */
p_scb->role = AVDT_OPEN_ACP;
avdt_ad_open_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, AVDT_ACP);
@@ -1080,12 +1106,12 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_reconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_reconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
AVDT_TRACE_DEBUG("%s: p_scb->peer_seid=%d p_data->msg.hdr.seid=%d", __func__,
p_scb->peer_seid, p_data->msg.hdr.seid);
A2DP_DumpCodecInfo(p_data->msg.config_cmd.p_cfg->codec_info);
- memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_scb->req_cfg = *p_data->msg.config_cmd.p_cfg;
p_data->msg.hdr.seid = p_scb->peer_seid;
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_RECONFIG, &p_data->msg);
}
@@ -1100,7 +1126,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_reconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_reconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->msg.hdr.err_code == 0) {
/* store new configuration */
if (p_scb->req_cfg.num_codec > 0) {
@@ -1131,7 +1157,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_security_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_security_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.seid = p_scb->peer_seid;
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SECURITY, &p_data->msg);
}
@@ -1145,7 +1171,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_security_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_security_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_data->msg.hdr.err_code == 0) {
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_SECURITY, &p_data->msg);
} else {
@@ -1163,7 +1189,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_setconfig_rej(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_setconfig_rej(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_scb->p_ccb != NULL) {
avdt_msg_send_rej(p_scb->p_ccb, AVDT_SIG_SETCONFIG, &p_data->msg);
@@ -1184,19 +1210,29 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_setconfig_req(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
- tAVDT_CFG *p_req, *p_cfg;
+void avdt_scb_snd_setconfig_req(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
+ AvdtpSepConfig *p_req, *p_cfg;
AVDT_TRACE_DEBUG("%s", __func__);
A2DP_DumpCodecInfo(p_data->msg.config_cmd.p_cfg->codec_info);
/* copy API parameters to scb, set scb as in use */
+
+ AvdtpCcb* p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
+ if (p_scb->p_ccb != p_ccb) {
+ AVDT_TRACE_ERROR(
+ "%s: mismatch in AVDTP SCB/CCB state: (p_scb->p_ccb=%p != p_ccb=%p): "
+ "p_scb=%p scb_handle=%d ccb_idx=%d",
+ __func__, p_scb->p_ccb, p_ccb, p_scb, p_scb->ScbHandle(),
+ p_data->msg.config_cmd.hdr.ccb_idx);
+ avdt_scb_rej_not_in_use(p_scb, p_data);
+ return;
+ }
p_scb->in_use = true;
- p_scb->p_ccb = avdt_ccb_by_idx(p_data->msg.config_cmd.hdr.ccb_idx);
p_scb->peer_seid = p_data->msg.config_cmd.hdr.seid;
p_req = p_data->msg.config_cmd.p_cfg;
- p_cfg = &p_scb->cs.cfg;
- memcpy(&p_scb->req_cfg, p_data->msg.config_cmd.p_cfg, sizeof(tAVDT_CFG));
+ p_cfg = &p_scb->stream_config.cfg;
+ p_scb->req_cfg = *p_data->msg.config_cmd.p_cfg;
avdt_msg_send_cmd(p_scb->p_ccb, p_scb, AVDT_SIG_SETCONFIG, &p_data->msg);
@@ -1215,9 +1251,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_setconfig_rsp(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_setconfig_rsp(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (p_scb->p_ccb != NULL) {
- memcpy(&p_scb->curr_cfg, &p_scb->req_cfg, sizeof(tAVDT_CFG));
+ p_scb->curr_cfg = p_scb->req_cfg;
avdt_msg_send_rsp(p_scb->p_ccb, AVDT_SIG_SETCONFIG, &p_data->msg);
}
@@ -1233,8 +1269,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_snd_tc_close(tAVDT_SCB* p_scb,
- UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_snd_tc_close(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
if (p_scb->curr_cfg.psc_mask & AVDT_PSC_REPORT)
avdt_ad_close_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
avdt_ad_close_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb);
@@ -1250,7 +1285,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_cb_err(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_cb_err(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* set error code and parameter */
@@ -1258,8 +1293,10 @@
avdt_ctrl.hdr.err_param = 0;
/* call callback, using lookup table to get callback event */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- avdt_scb_cback_evt[p_scb->curr_evt], &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty,
+ avdt_scb_cback_evt[p_scb->curr_evt], &avdt_ctrl,
+ p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -1272,7 +1309,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_cong_state(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_cong_state(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_scb->cong = p_data->llcong;
}
@@ -1286,7 +1323,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_rej_state(UNUSED_ATTR tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_rej_state(UNUSED_ATTR AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.err_code = AVDT_ERR_BAD_STATE;
p_data->msg.hdr.err_param = 0;
avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
@@ -1303,7 +1340,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_rej_in_use(UNUSED_ATTR tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_rej_in_use(UNUSED_ATTR AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.err_code = AVDT_ERR_IN_USE;
p_data->msg.hdr.err_param = 0;
avdt_msg_send_rej(avdt_ccb_by_idx(p_data->msg.hdr.ccb_idx),
@@ -1320,7 +1357,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_rej_not_in_use(UNUSED_ATTR tAVDT_SCB* p_scb,
+void avdt_scb_rej_not_in_use(UNUSED_ATTR AvdtpScb* p_scb,
tAVDT_SCB_EVT* p_data) {
p_data->msg.hdr.err_code = AVDT_ERR_NOT_IN_USE;
p_data->msg.hdr.err_param = 0;
@@ -1337,7 +1374,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_set_remove(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_set_remove(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
p_scb->remove = true;
}
@@ -1350,7 +1387,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_free_pkt(tAVDT_SCB* p_scb, tAVDT_SCB_EVT* p_data) {
+void avdt_scb_free_pkt(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
/* set error code and parameter */
@@ -1362,8 +1399,9 @@
AVDT_TRACE_WARNING("Dropped media packet");
/* we need to call callback to keep data flow going */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
- &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl, p_scb->stream_config.scb_index);
}
/*******************************************************************************
@@ -1375,9 +1413,9 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_clr_pkt(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_clr_pkt(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
- tAVDT_CCB* p_ccb;
+ AvdtpCcb* p_ccb;
uint8_t tcid;
uint16_t lcid;
@@ -1390,7 +1428,7 @@
/* get tcid from type, scb */
tcid = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb);
- lcid = avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
+ lcid = avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid;
L2CA_FlushChannel(lcid, L2CAP_FLUSH_CHANS_ALL);
}
@@ -1400,8 +1438,9 @@
AVDT_TRACE_DEBUG("Dropped stored media packet");
/* we need to call callback to keep data flow going */
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL, AVDT_WRITE_CFM_EVT,
- &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl, p_scb->stream_config.scb_index);
}
}
@@ -1417,7 +1456,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_chk_snd_pkt(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_chk_snd_pkt(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
tAVDT_CTRL avdt_ctrl;
BT_HDR* p_pkt;
@@ -1429,8 +1468,9 @@
p_scb->p_pkt = NULL;
avdt_ad_write_req(AVDT_CHAN_MEDIA, p_scb->p_ccb, p_scb, p_pkt);
- (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,
- AVDT_WRITE_CFM_EVT, &avdt_ctrl);
+ (*p_scb->stream_config.p_avdt_ctrl_cback)(
+ avdt_scb_to_hdl(p_scb), RawAddress::kEmpty, AVDT_WRITE_CFM_EVT,
+ &avdt_ctrl, p_scb->stream_config.scb_index);
}
}
}
@@ -1446,7 +1486,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_transport_channel_timer(tAVDT_SCB* p_scb,
+void avdt_scb_transport_channel_timer(AvdtpScb* p_scb,
UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
alarm_set_on_mloop(p_scb->transport_channel_timer,
AVDT_SCB_TC_DISC_TIMEOUT_MS,
@@ -1462,8 +1502,7 @@
* Returns Nothing.
*
******************************************************************************/
-void avdt_scb_clr_vars(tAVDT_SCB* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
+void avdt_scb_clr_vars(AvdtpScb* p_scb, UNUSED_ATTR tAVDT_SCB_EVT* p_data) {
p_scb->in_use = false;
- p_scb->p_ccb = NULL;
p_scb->peer_seid = 0;
}
diff --git a/stack/btm/btm_acl.cc b/stack/btm/btm_acl.cc
index 5697fe2..10ac2a5 100644
--- a/stack/btm/btm_acl.cc
+++ b/stack/btm/btm_acl.cc
@@ -191,8 +191,9 @@
tACL_CONN* p;
uint8_t xx;
- BTM_TRACE_DEBUG("btm_acl_created hci_handle=%d link_role=%d transport=%d",
- hci_handle, link_role, transport);
+ BTM_TRACE_DEBUG("%s: peer %s hci_handle=%d link_role=%d transport=%d",
+ __func__, bda.ToString().c_str(), hci_handle, link_role,
+ transport);
/* Ensure we don't have duplicates */
p = btm_bda_to_acl(bda, transport);
if (p != (tACL_CONN*)NULL) {
@@ -240,7 +241,8 @@
p_dev_rec = btm_find_dev_by_handle(hci_handle);
if (p_dev_rec) {
- BTM_TRACE_DEBUG("device_type=0x%x", p_dev_rec->device_type);
+ BTM_TRACE_DEBUG("%s: peer %s device_type=0x%x", __func__,
+ bda.ToString().c_str(), p_dev_rec->device_type);
}
if (p_dev_rec && !(transport == BT_TRANSPORT_LE)) {
@@ -690,8 +692,8 @@
(*btm_cb.p_bl_changed_cb)(&btm_bl_event_data);
BTM_TRACE_DEBUG(
- "Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, rs_st:%d",
- evt.new_role, evt.hci_status, p->switch_role_state);
+ "%s: Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, rs_st:%d",
+ __func__, evt.new_role, evt.hci_status, p->switch_role_state);
}
#if (BTM_DISC_DURING_RS == TRUE)
@@ -1435,7 +1437,9 @@
tBTM_ROLE_SWITCH_CMPL* p_data = &btm_cb.devcb.switch_role_ref_data;
tBTM_SEC_DEV_REC* p_dev_rec;
- BTM_TRACE_DEBUG("btm_acl_role_changed");
+ BTM_TRACE_DEBUG("%s: peer %s hci_status:0x%x new_role:%d", __func__,
+ (p_bda != nullptr) ? bd_addr->ToString().c_str() : "nullptr",
+ hci_status, new_role);
/* Ignore any stray events */
if (p == NULL) {
/* it could be a failure */
@@ -1498,7 +1502,9 @@
}
BTM_TRACE_DEBUG(
- "Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, rs_st:%d",
+ "%s: peer %s Role Switch Event: new_role 0x%02x, HCI Status 0x%02x, "
+ "rs_st:%d",
+ __func__, (p_bda != nullptr) ? p_bda->ToString().c_str() : "nullptr",
p_data->role, p_data->hci_status, p->switch_role_state);
#if (BTM_DISC_DURING_RS == TRUE)
@@ -1507,10 +1513,13 @@
if (p_dev_rec != NULL) {
if (p_dev_rec->rs_disc_pending == BTM_SEC_DISC_PENDING) {
BTM_TRACE_WARNING(
- "btm_acl_role_changed -> Issuing delayed HCI_Disconnect!!!");
+ "%s peer %s Issuing delayed HCI_Disconnect!!!", __func__,
+ (p_bda != nullptr) ? p_bda->ToString().c_str() : "nullptr");
btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
}
- BTM_TRACE_ERROR("tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
+ BTM_TRACE_ERROR("%s: peer %s tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
+ __func__,
+ (p_bda != nullptr) ? p_bda->ToString().c_str() : "nullptr",
PTR_TO_UINT(p_dev_rec), p_dev_rec->rs_disc_pending);
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
}
diff --git a/stack/include/a2dp_aac.h b/stack/include/a2dp_aac.h
index f2d2553..a3a53b1 100644
--- a/stack/include/a2dp_aac.h
+++ b/stack/include/a2dp_aac.h
@@ -243,12 +243,12 @@
// Gets the A2DP AAC Sink codec name.
const char* A2DP_CodecIndexStrAacSink(void);
-// Initializes A2DP AAC Source codec information into |tAVDT_CFG|
+// Initializes A2DP AAC Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigAac(tAVDT_CFG* p_cfg);
+bool A2DP_InitCodecConfigAac(AvdtpSepConfig* p_cfg);
-// Initializes A2DP AAC Sink codec information into |tAVDT_CFG|
+// Initializes A2DP AAC Sink codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigAacSink(tAVDT_CFG* p_cfg);
+bool A2DP_InitCodecConfigAacSink(AvdtpSepConfig* p_cfg);
#endif // A2DP_AAC_H
diff --git a/stack/include/a2dp_codec_api.h b/stack/include/a2dp_codec_api.h
index ba62fbe..0db1f16 100644
--- a/stack/include/a2dp_codec_api.h
+++ b/stack/include/a2dp_codec_api.h
@@ -658,11 +658,12 @@
// Gets the A2DP codec name for a given |codec_index|.
const char* A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index);
-// Initializes A2DP codec-specific information into |tAVDT_CFG| configuration
-// entry pointed by |p_cfg|. The selected codec is defined by |codec_index|.
+// Initializes A2DP codec-specific information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|. The selected codec is defined
+// by |codec_index|.
// Returns true on success, otherwise false.
bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
+ AvdtpSepConfig* p_cfg);
// Decodes and displays A2DP codec info when using |LOG_DEBUG|.
// |p_codec_info| is a pointer to the codec_info to decode and display.
diff --git a/stack/include/a2dp_sbc.h b/stack/include/a2dp_sbc.h
index 51632ad..393a6e9 100644
--- a/stack/include/a2dp_sbc.h
+++ b/stack/include/a2dp_sbc.h
@@ -250,12 +250,12 @@
// Gets the A2DP SBC Sink codec name.
const char* A2DP_CodecIndexStrSbcSink(void);
-// Initializes A2DP SBC Source codec information into |tAVDT_CFG| configuration
-// entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg);
+// Initializes A2DP SBC Source codec information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|.
+bool A2DP_InitCodecConfigSbc(AvdtpSepConfig* p_cfg);
-// Initializes A2DP SBC Sink codec information into |tAVDT_CFG| configuration
-// entry pointed by |p_cfg|.
-bool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg);
+// Initializes A2DP SBC Sink codec information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|.
+bool A2DP_InitCodecConfigSbcSink(AvdtpSepConfig* p_cfg);
#endif // A2DP_SBC_H
diff --git a/stack/include/a2dp_vendor.h b/stack/include/a2dp_vendor.h
index 0547d46..9d0b635 100644
--- a/stack/include/a2dp_vendor.h
+++ b/stack/include/a2dp_vendor.h
@@ -187,12 +187,12 @@
// Gets the A2DP vendor codec name for a given |codec_index|.
const char* A2DP_VendorCodecIndexStr(btav_a2dp_codec_index_t codec_index);
-// Initializes A2DP vendor codec-specific information into |tAVDT_CFG|
+// Initializes A2DP vendor codec-specific information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|. The selected codec is defined by
// |codec_index|.
// Returns true on success, otherwise false.
bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,
- tAVDT_CFG* p_cfg);
+ AvdtpSepConfig* p_cfg);
// Decodes and displays A2DP vendor codec info when using |LOG_DEBUG|.
// |p_codec_info| is a pointer to the codec_info to decode and display.
diff --git a/stack/include/a2dp_vendor_aptx.h b/stack/include/a2dp_vendor_aptx.h
index a9420f1..2cece9b 100644
--- a/stack/include/a2dp_vendor_aptx.h
+++ b/stack/include/a2dp_vendor_aptx.h
@@ -139,8 +139,8 @@
// Gets the A2DP aptX Source codec name.
const char* A2DP_VendorCodecIndexStrAptx(void);
-// Initializes A2DP aptX Source codec information into |tAVDT_CFG|
+// Initializes A2DP aptX Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_VendorInitCodecConfigAptx(tAVDT_CFG* p_cfg);
+bool A2DP_VendorInitCodecConfigAptx(AvdtpSepConfig* p_cfg);
#endif // A2DP_VENDOR_APTX_H
diff --git a/stack/include/a2dp_vendor_aptx_hd.h b/stack/include/a2dp_vendor_aptx_hd.h
index e45fa0c..3508040 100644
--- a/stack/include/a2dp_vendor_aptx_hd.h
+++ b/stack/include/a2dp_vendor_aptx_hd.h
@@ -140,8 +140,8 @@
// Gets the A2DP aptX-HD Source codec name.
const char* A2DP_VendorCodecIndexStrAptxHd(void);
-// Initializes A2DP aptX-HD Source codec information into |tAVDT_CFG|
+// Initializes A2DP aptX-HD Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_VendorInitCodecConfigAptxHd(tAVDT_CFG* p_cfg);
+bool A2DP_VendorInitCodecConfigAptxHd(AvdtpSepConfig* p_cfg);
#endif // A2DP_VENDOR_APTX_HD_H
diff --git a/stack/include/a2dp_vendor_ldac.h b/stack/include/a2dp_vendor_ldac.h
index e8689e5..9732d07 100644
--- a/stack/include/a2dp_vendor_ldac.h
+++ b/stack/include/a2dp_vendor_ldac.h
@@ -146,8 +146,8 @@
// Gets the A2DP LDAC Source codec name.
const char* A2DP_VendorCodecIndexStrLdac(void);
-// Initializes A2DP LDAC Source codec information into |tAVDT_CFG|
+// Initializes A2DP LDAC Source codec information into |AvdtpSepConfig|
// configuration entry pointed by |p_cfg|.
-bool A2DP_VendorInitCodecConfigLdac(tAVDT_CFG* p_cfg);
+bool A2DP_VendorInitCodecConfigLdac(AvdtpSepConfig* p_cfg);
#endif // A2DP_VENDOR_LDAC_H
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index dd96856..8cbbb6c 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -236,11 +236,6 @@
/* PSM for AVDT */
#define AVDT_PSM 0x0019
-/* Nonsupported protocol command messages. This value is used in tAVDT_CS */
-#define AVDT_NSC_SUSPEND 0x01 /* Suspend command not supported */
-#define AVDT_NSC_RECONFIG 0x02 /* Reconfigure command not supported */
-#define AVDT_NSC_SECURITY 0x04 /* Security command not supported */
-
/*****************************************************************************
* Type Definitions
****************************************************************************/
@@ -270,14 +265,36 @@
uint8_t cname[AVDT_MAX_CNAME_SIZE + 1];
} tAVDT_REPORT_DATA;
-/* This structure contains parameters which are set at registration. */
-typedef struct {
+/**
+ * AVDTP Registration Control Block.
+ */
+class AvdtpRcb {
+ public:
+ AvdtpRcb()
+ : ctrl_mtu(0),
+ ret_tout(0),
+ sig_tout(0),
+ idle_tout(0),
+ sec_mask(0),
+ scb_index(0) {}
+ AvdtpRcb& operator=(const AvdtpRcb&) = default;
+
+ void Reset() {
+ ctrl_mtu = 0;
+ ret_tout = 0;
+ sig_tout = 0;
+ idle_tout = 0;
+ sec_mask = 0;
+ scb_index = 0;
+ }
+
uint16_t ctrl_mtu; /* L2CAP MTU of the AVDTP signaling channel */
uint8_t ret_tout; /* AVDTP signaling retransmission timeout */
uint8_t sig_tout; /* AVDTP signaling message timeout */
uint8_t idle_tout; /* AVDTP idle signaling channel timeout */
uint8_t sec_mask; /* Security mask for BTM_SetSecurityLevel() */
-} tAVDT_REG;
+ uint8_t scb_index; /* The Stream Control Block index */
+};
/* This structure contains the SEP information. This information is
* transferred during the discovery procedure.
@@ -289,8 +306,35 @@
uint8_t tsep; /* SEP type */
} tAVDT_SEP_INFO;
-/* This structure contains the SEP configuration. */
-typedef struct {
+/**
+ * AVDTP SEP Configuration.
+ */
+class AvdtpSepConfig {
+ public:
+ AvdtpSepConfig()
+ : codec_info{},
+ protect_info{},
+ num_codec(0),
+ num_protect(0),
+ psc_mask(0),
+ recov_type(0),
+ recov_mrws(0),
+ recov_mnmp(0),
+ hdrcmp_mask(0) {}
+ AvdtpSepConfig& operator=(const AvdtpSepConfig&) = default;
+
+ void Reset() {
+ memset(codec_info, 0, sizeof(codec_info));
+ memset(protect_info, 0, sizeof(protect_info));
+ num_codec = 0;
+ num_protect = 0;
+ psc_mask = 0;
+ recov_type = 0;
+ recov_mrws = 0;
+ recov_mnmp = 0;
+ hdrcmp_mask = 0;
+ }
+
uint8_t codec_info[AVDT_CODEC_SIZE]; /* Codec capabilities array */
uint8_t protect_info[AVDT_PROTECT_SIZE]; /* Content protection capabilities */
uint8_t num_codec; /* Number of media codec information elements */
@@ -300,7 +344,7 @@
uint8_t recov_mrws; /* Maximum recovery window size */
uint8_t recov_mnmp; /* Recovery maximum number of media packets */
uint8_t hdrcmp_mask; /* Header compression capabilities */
-} tAVDT_CFG;
+};
/* Header structure for callback event parameters. */
typedef struct {
@@ -318,13 +362,13 @@
*/
typedef struct {
tAVDT_EVT_HDR hdr; /* Event header */
- tAVDT_CFG* p_cfg; /* Pointer to configuration for this SEP */
+ AvdtpSepConfig* p_cfg; /* Pointer to configuration for this SEP */
} tAVDT_CONFIG;
/* This data structure is associated with the AVDT_CONFIG_IND_EVT. */
typedef struct {
tAVDT_EVT_HDR hdr; /* Event header */
- tAVDT_CFG* p_cfg; /* Pointer to configuration for this SEP */
+ AvdtpSepConfig* p_cfg; /* Pointer to configuration for this SEP */
uint8_t int_seid; /* Stream endpoint ID of stream initiating the operation */
} tAVDT_SETCONFIG;
@@ -384,8 +428,9 @@
* endpoints and for the AVDT_DiscoverReq() and AVDT_GetCapReq() functions.
*
*/
-typedef void(tAVDT_CTRL_CBACK)(uint8_t handle, const RawAddress* bd_addr,
- uint8_t event, tAVDT_CTRL* p_data);
+typedef void(tAVDT_CTRL_CBACK)(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index);
/* This is the data callback function. It is executed when AVDTP has a media
* packet ready for the application. This function is required for SNK
@@ -401,23 +446,57 @@
typedef void(tAVDT_REPORT_CBACK)(uint8_t handle, AVDT_REPORT_TYPE type,
tAVDT_REPORT_DATA* p_data);
-typedef uint16_t(tAVDT_GETCAP_REQ)(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback);
+/**
+ * AVDTP Stream Configuration.
+ * The information is used when a stream is created.
+ */
+class AvdtpStreamConfig {
+ public:
+ //
+ // Non-supported protocol command messages
+ //
+ // Suspend command not supported
+ static constexpr int AVDT_NSC_SUSPEND = 0x01;
+ // Reconfigure command not supported
+ static constexpr int AVDT_NSC_RECONFIG = 0x02;
+ // Security command not supported
+ static constexpr int AVDT_NSC_SECURITY = 0x04;
-/* This structure contains information required when a stream is created.
- * It is passed to the AVDT_CreateStream() function.
-*/
-typedef struct {
- tAVDT_CFG cfg; /* SEP configuration */
- tAVDT_CTRL_CBACK* p_ctrl_cback; /* Control callback function */
- tAVDT_SINK_DATA_CBACK* p_sink_data_cback; /* Sink data callback function */
- tAVDT_REPORT_CBACK* p_report_cback; /* Report callback function. */
- uint16_t mtu; /* The L2CAP MTU of the transport channel */
- uint16_t flush_to; /* The L2CAP flush timeout of the transport channel */
- uint8_t tsep; /* SEP type */
- uint8_t media_type; /* Media type: AVDT_MEDIA_TYPE_* */
- uint16_t nsc_mask; /* Nonsupported protocol command messages */
-} tAVDT_CS;
+ AvdtpStreamConfig()
+ : p_avdt_ctrl_cback(nullptr),
+ scb_index(0),
+ p_sink_data_cback(nullptr),
+ p_report_cback(nullptr),
+ mtu(0),
+ flush_to(0),
+ tsep(0),
+ media_type(0),
+ nsc_mask(0) {}
+
+ void Reset() {
+ cfg.Reset();
+ p_avdt_ctrl_cback = nullptr;
+ scb_index = 0;
+ p_sink_data_cback = nullptr;
+ p_report_cback = nullptr;
+ mtu = 0;
+ flush_to = 0;
+ tsep = 0;
+ media_type = 0;
+ nsc_mask = 0;
+ }
+
+ AvdtpSepConfig cfg; // SEP configuration
+ tAVDT_CTRL_CBACK* p_avdt_ctrl_cback; // Control callback function
+ uint8_t scb_index; // The index to the bta_av_cb.p_scb[] entry
+ tAVDT_SINK_DATA_CBACK* p_sink_data_cback; // Sink data callback function
+ tAVDT_REPORT_CBACK* p_report_cback; // Report callback function
+ uint16_t mtu; // The L2CAP MTU of the transport channel
+ uint16_t flush_to; // The L2CAP flush timeout of the transport channel
+ uint8_t tsep; // SEP type
+ uint8_t media_type; // Media type: AVDT_MEDIA_TYPE_*
+ uint16_t nsc_mask; // Nonsupported protocol command messages
+};
/* AVDT data option mask is used in the write request */
#define AVDT_DATA_OPT_NONE 0x00 /* No option still add RTP header */
@@ -443,7 +522,7 @@
* Returns void
*
******************************************************************************/
-extern void AVDT_Register(tAVDT_REG* p_reg, tAVDT_CTRL_CBACK* p_cback);
+extern void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback);
/*******************************************************************************
*
@@ -485,7 +564,8 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_CreateStream(uint8_t* p_handle, tAVDT_CS* p_cs);
+extern uint16_t AVDT_CreateStream(uint8_t peer_id, uint8_t* p_handle,
+ const AvdtpStreamConfig& avdtp_stream_config);
/*******************************************************************************
*
@@ -530,6 +610,7 @@
*
******************************************************************************/
extern uint16_t AVDT_DiscoverReq(const RawAddress& bd_addr,
+ uint8_t channel_index,
tAVDT_SEP_INFO* p_sep_info, uint8_t max_seps,
tAVDT_CTRL_CBACK* p_cback);
@@ -557,35 +638,9 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback);
-
-/*******************************************************************************
- *
- * Function AVDT_GetAllCapReq
- *
- * Description This function initiates a connection to the AVDTP service
- * on the peer device, if not already present, and gets the
- * capabilities of a stream endpoint on the peer device.
- * This function can be called at any time regardless of
- * whether there is an AVDTP connection to the peer device.
- *
- * When the procedure is complete, an AVDT_GETCAP_CFM_EVT is
- * sent to the application via its callback function. The
- * application must not call AVDT_GetCapReq() or
- * AVDT_DiscoverReq() again until the procedure is complete.
- *
- * The memory pointed to by p_cfg is allocated by the
- * application. This memory is written to by AVDTP as part
- * of the get capabilities procedure. This memory must
- * remain accessible until the application receives
- * the AVDT_GETCAP_CFM_EVT.
- *
- * Returns AVDT_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern uint16_t AVDT_GetAllCapReq(const RawAddress& bd_addr, uint8_t seid,
- tAVDT_CFG* p_cfg, tAVDT_CTRL_CBACK* p_cback);
+extern uint16_t AVDT_GetCapReq(const RawAddress& bd_addr, uint8_t channel_index,
+ uint8_t seid, AvdtpSepConfig* p_cfg,
+ tAVDT_CTRL_CBACK* p_cback, bool get_all_cap);
/*******************************************************************************
*
@@ -615,7 +670,8 @@
*
******************************************************************************/
extern uint16_t AVDT_OpenReq(uint8_t handle, const RawAddress& bd_addr,
- uint8_t seid, tAVDT_CFG* p_cfg);
+ uint8_t channel_index, uint8_t seid,
+ AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
@@ -699,7 +755,7 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_ReconfigReq(uint8_t handle, tAVDT_CFG* p_cfg);
+extern uint16_t AVDT_ReconfigReq(uint8_t handle, AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
@@ -841,7 +897,8 @@
* Returns AVDT_SUCCESS if successful, otherwise error.
*
******************************************************************************/
-extern uint16_t AVDT_ConnectReq(const RawAddress& bd_addr, uint8_t sec_mask,
+extern uint16_t AVDT_ConnectReq(const RawAddress& bd_addr,
+ uint8_t channel_index, uint8_t sec_mask,
tAVDT_CTRL_CBACK* p_cback);
/*******************************************************************************
@@ -920,4 +977,12 @@
*****************************************************************************/
extern uint8_t AVDT_SetTraceLevel(uint8_t new_level);
+/**
+ * Dump debug-related information for the Stack AVDTP module.
+ *
+ * @param fd the file descriptor to use for writing the ASCII formatted
+ * information
+ */
+void stack_debug_avdtp_api_dump(int fd);
+
#endif /* AVDT_API_H */
diff --git a/stack/include/avdtc_api.h b/stack/include/avdtc_api.h
index 71f2472..6948f83 100644
--- a/stack/include/avdtc_api.h
+++ b/stack/include/avdtc_api.h
@@ -107,7 +107,7 @@
*
******************************************************************************/
extern void AVDTC_GetCapRsp(const RawAddress& bd_addr, uint8_t label,
- tAVDT_CFG* p_cap);
+ AvdtpSepConfig* p_cap);
/*******************************************************************************
*
@@ -119,7 +119,7 @@
*
******************************************************************************/
extern void AVDTC_GetAllCapRsp(const RawAddress& bd_addr, uint8_t label,
- tAVDT_CFG* p_cap);
+ AvdtpSepConfig* p_cap);
/*******************************************************************************
*
@@ -141,7 +141,8 @@
* Returns void
*
******************************************************************************/
-extern void AVDTC_GetConfigRsp(uint8_t handle, uint8_t label, tAVDT_CFG* p_cfg);
+extern void AVDTC_GetConfigRsp(uint8_t handle, uint8_t label,
+ AvdtpSepConfig* p_cfg);
/*******************************************************************************
*
diff --git a/stack/test/stack_a2dp_test.cc b/stack/test/stack_a2dp_test.cc
index 91c1c83..d53818d 100644
--- a/stack/test/stack_a2dp_test.cc
+++ b/stack/test/stack_a2dp_test.cc
@@ -773,7 +773,7 @@
}
TEST_F(StackA2dpTest, test_a2dp_init_codec_config) {
- tAVDT_CFG avdt_cfg;
+ AvdtpSepConfig avdt_cfg;
//
// Test for SBC Source
diff --git a/test/run_host_unit_tests.py b/test/run_host_unit_tests.py
index e5e392c..7c7c9d0 100755
--- a/test/run_host_unit_tests.py
+++ b/test/run_host_unit_tests.py
@@ -22,6 +22,7 @@
# Must have 'host_supported: true'
HOST_TESTS = [
'bluetoothtbd_test',
+ 'net_test_btif_state_machine',
'net_test_btcore',
'net_test_types',
]
diff --git a/test/run_unit_tests.sh b/test/run_unit_tests.sh
index 4c390bf..3b5a731 100755
--- a/test/run_unit_tests.sh
+++ b/test/run_unit_tests.sh
@@ -8,6 +8,7 @@
net_test_bta
net_test_btif
net_test_btif_profile_queue
+ net_test_btif_state_machine
net_test_device
net_test_hci
net_test_stack