Stability fixes for a2dp hal control path
Ensure av statemachine is preventing a2dp hal to restart the stream
when not ready. This prevents ending up in a scenario where a2dp hal
locks up. Code cleanup.
bug 7002859
Change-Id: I3f3eeaab4ca185733b8b0042ed2cfa701f76a203
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h
old mode 100644
new mode 100755
index b3b72e7..55c88d5
--- a/btif/include/btif_media.h
+++ b/btif/include/btif_media.h
@@ -237,6 +237,7 @@
void btif_a2dp_on_idle(void);
void btif_a2dp_on_open(void);
void btif_a2dp_on_started(tBTA_AV_START *p_av);
+void btif_a2dp_ack_fail(void);
void btif_a2dp_on_stop_req(void);
void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av);
void btif_a2dp_on_suspend(void);
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index 074164d..fbbd564 100755
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -62,6 +62,8 @@
#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
/*****************************************************************************
** Local type definitions
@@ -401,6 +403,7 @@
/* wait for audioflinger to stop a2dp */
break;
+ case BTA_AV_STOP_EVT:
case BTIF_AV_STOP_STREAM_REQ_EVT:
/* immediately flush any pending tx frames while suspend is pending */
btif_a2dp_set_tx_flush(TRUE);
@@ -462,15 +465,19 @@
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;
btif_media_check_iop_exceptions(btif_av_cb.peer_bda.address);
- break;
+ break;
case BTIF_SM_EXIT_EVT:
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
break;
case BTIF_AV_START_STREAM_REQ_EVT:
btif_a2dp_setup_codec();
BTA_AvStart();
+ btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
break;
case BTA_AV_START_EVT:
@@ -478,6 +485,7 @@
BTIF_TRACE_EVENT3("BTA_AV_START_EVT status %d, suspending %d, init %d",
p_av->start.status, p_av->start.suspending, p_av->start.initiator);
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
return TRUE;
@@ -502,6 +510,9 @@
case BTA_AV_CLOSE_EVT:
+ /* avdtp link is closed */
+ btif_a2dp_on_stopped(NULL);
+
/* inform the application that we are disconnected */
HAL_CBACK(bt_av_callbacks, connection_state_cb,
BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
@@ -509,6 +520,20 @@
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_WARNING0("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_ack_fail();
+ }
+ break;
+
CHECK_RC_EVENT(event, p_data);
default:
@@ -551,6 +576,11 @@
case BTIF_SM_EXIT_EVT:
break;
+ case BTIF_AV_START_STREAM_REQ_EVT:
+ /* we were remotely started, just ack back the local request */
+ btif_a2dp_on_started(NULL);
+ 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:
@@ -627,6 +657,8 @@
case BTA_AV_STOP_EVT:
+ btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+
btif_a2dp_on_stopped(&p_av->suspend);
HAL_CBACK(bt_av_callbacks, audio_state_cb,
@@ -640,6 +672,8 @@
case BTA_AV_CLOSE_EVT:
+ btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+
/* avdtp link is closed */
btif_a2dp_on_stopped(NULL);
@@ -854,8 +888,8 @@
return FALSE;
}
- /* check if we are remotely suspended */
- if (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND)
+ /* 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))
return FALSE;
return (state == BTIF_AV_STATE_OPENED);
@@ -878,9 +912,9 @@
BTIF_TRACE_DEBUG3("btif_av_stream_started : sm hdl %d, state %d, flags %x",
btif_av_cb.sm_handle, state, btif_av_cb.flags);
- /* don't allow media task to start if we are suspending or
- remotely suspended (not yet changed state) */
- if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND))
+ /* 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))
return FALSE;
return (state == BTIF_AV_STATE_STARTED);
@@ -958,11 +992,11 @@
/*******************************************************************************
**
-** Function btif_av_is_rc_open_without_a2dp
+** Function btif_av_is_connected
**
-** Description Checks if GAVDTP Open notification to app is pending (2 second timer)
+** Description Checks if av has a connected sink
**
-** Returns boolean
+** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN btif_av_is_connected(void)
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 200cf06..3c15b27 100755
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -35,6 +35,7 @@
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
+#include <errno.h>
#include "bt_target.h"
#include "gki.h"
@@ -51,11 +52,9 @@
#include "bta_av_ci.h"
#include "l2c_api.h"
-
#include "btif_av_co.h"
#include "btif_media.h"
-
#if (BTA_AV_INCLUDED == TRUE)
#include "sbc_encoder.h"
#endif
@@ -166,7 +165,7 @@
#define BT_MEDIA_TASK A2DP_MEDIA_TASK
#define USEC_PER_SEC 1000000L
-#define TPUT_STATS_INTERVAL_US (1000*1000)
+#define TPUT_STATS_INTERVAL_US (3000*1000)
/*
* CONGESTION COMPENSATION CTRL ::
@@ -234,11 +233,11 @@
} tBTIF_MEDIA_CB;
typedef struct {
- int rx;
- int rx_tot;
- int tx;
- int tx_tot;
- int ts_prev_us;
+ long long rx;
+ long long rx_tot;
+ long long tx;
+ long long tx_tot;
+ long long ts_prev_us;
} t_stat;
/*****************************************************************************
@@ -256,6 +255,7 @@
static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
static void btif_a2dp_encoder_update(void);
+const char* dump_media_event(UINT16 event);
/*****************************************************************************
** Externs
@@ -286,8 +286,8 @@
/* only monitor one connection at a time for now */
static t_stat cur_stat;
struct timespec now;
- unsigned int prev_us;
- unsigned int now_us;
+ unsigned long long prev_us;
+ unsigned long long now_us;
if (reset == TRUE)
{
@@ -309,14 +309,12 @@
now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
- //APPL_TRACE_DEBUG1("%d us", now_us - cur_stat.ts_prev_us);
-
if ((now_us - cur_stat.ts_prev_us) < TPUT_STATS_INTERVAL_US)
return;
- APPL_TRACE_WARNING4("tput rx:%d, tx:%d (kB/s) (tot : rx %d, tx %d bytes)",
- (cur_stat.rx)/((now_us - cur_stat.ts_prev_us)/1000),
- (cur_stat.tx)/((now_us - cur_stat.ts_prev_us)/1000),
+ APPL_TRACE_WARNING4("tput rx:%d, tx:%d (bytes/s) (tot : rx %d, tx %d bytes)",
+ (cur_stat.rx*1000000)/((now_us - cur_stat.ts_prev_us)),
+ (cur_stat.tx*1000000)/((now_us - cur_stat.ts_prev_us)),
cur_stat.rx_tot, cur_stat.tx_tot);
/* stats dumped. now reset stats for next interval */
@@ -401,7 +399,8 @@
{
UINT8 ack = status;
- APPL_TRACE_EVENT2("## a2dp ack : %s, status %d ##", dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
+ APPL_TRACE_EVENT2("## a2dp ack : %s, status %d ##",
+ dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
/* sanity check */
if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_NONE)
@@ -838,11 +837,17 @@
void btif_a2dp_on_started(tBTA_AV_START *p_av)
{
- tBTIF_AV_MEDIA_FEEDINGS media_feeding;
tBTIF_STATUS status;
APPL_TRACE_EVENT0("## ON A2DP STARTED ##");
+ if (p_av == NULL)
+ {
+ /* ack back a local start request */
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+ return;
+ }
+
if (p_av->status == BTA_AV_SUCCESS)
{
if (p_av->suspending == FALSE)
@@ -870,6 +875,24 @@
/*****************************************************************************
**
+** Function btif_a2dp_ack_fail
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+
+void btif_a2dp_ack_fail(void)
+{
+ tBTIF_STATUS status;
+
+ APPL_TRACE_EVENT0("## A2DP_CTRL_ACK_FAILURE ##");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+}
+
+/*****************************************************************************
+**
** Function btif_a2dp_on_stopped
**
** Description
@@ -1182,7 +1205,8 @@
*******************************************************************************/
static void btif_media_task_handle_cmd(BT_HDR *p_msg)
{
- VERBOSE("btif_media_task_handle_cmd : %d %s", p_msg->event, dump_media_event(p_msg->event));
+ VERBOSE("btif_media_task_handle_cmd : %d %s", p_msg->event,
+ dump_media_event(p_msg->event));
switch (p_msg->event)
{
@@ -1467,7 +1491,8 @@
/* Only update the bitrate and MTU size while timer is running to make sure it has been initialized */
//if (btif_media_cb.is_tx_timer)
{
- btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
+ btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE -
+ BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
< pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET
- sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
@@ -1533,11 +1558,13 @@
s16BitPool = 0;
}
- APPL_TRACE_EVENT2("bitpool candidate : %d (%d kbps)", s16BitPool, pstrEncParams->u16BitRate);
+ APPL_TRACE_EVENT2("bitpool candidate : %d (%d kbps)",
+ s16BitPool, pstrEncParams->u16BitRate);
if (s16BitPool > pUpdateAudio->MaxBitPool)
{
- APPL_TRACE_WARNING1("btif_media_task_enc_update computed bitpool too large (%d)", s16BitPool);
+ APPL_TRACE_DEBUG1("btif_media_task_enc_update computed bitpool too large (%d)",
+ s16BitPool);
/* Decrease bitrate */
btif_media_cb.encoder.u16BitRate -= BTIF_MEDIA_BITRATE_STEP;
/* Record that we have decreased the bitrate */
@@ -1592,7 +1619,6 @@
APPL_TRACE_DEBUG1("num_channel:%d", p_feeding->feeding.cfg.pcm.num_channel);
APPL_TRACE_DEBUG1("bit_per_sample:%d", p_feeding->feeding.cfg.pcm.bit_per_sample);
-
/* Check the PCM feeding sampling_freq */
switch (p_feeding->feeding.cfg.pcm.sampling_freq)
{
@@ -1639,11 +1665,13 @@
if (reconfig_needed != FALSE)
{
- APPL_TRACE_DEBUG0("btif_media_task_pcm2sbc_init calls SBC_Encoder_Init");
- APPL_TRACE_DEBUG1("btif_media_task_pcm2sbc_init mtu %d", btif_media_cb.TxAaMtuSize);
- APPL_TRACE_DEBUG6("btif_media_task_pcm2sbc_init ch mode %d, nbsubd %d, nb blk %d, alloc method %d, bit rate %d, Smp freq %d",
- btif_media_cb.encoder.s16ChannelMode, btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
- btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, btif_media_cb.encoder.s16SamplingFreq);
+ APPL_TRACE_DEBUG1("btif_media_task_pcm2sbc_init :: mtu %d", btif_media_cb.TxAaMtuSize);
+ APPL_TRACE_DEBUG6("ch mode %d, nbsubd %d, nb %d, alloc %d, rate %d, freq %d",
+ btif_media_cb.encoder.s16ChannelMode,
+ btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
+ btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate,
+ btif_media_cb.encoder.s16SamplingFreq);
+
SBC_Encoder_Init(&(btif_media_cb.encoder));
}
else
@@ -1740,8 +1768,7 @@
static void btif_media_task_aa_start_tx(void)
{
APPL_TRACE_DEBUG2("btif_media_task_aa_start_tx is timer %d, feeding mode %d",
- btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode);
-
+ btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode);
/* Use a timer to poll the UIPC, get rid of the UIPC call back */
// UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REG_CBACK, NULL);
@@ -1751,7 +1778,9 @@
/* Reset the media feeding state */
btif_media_task_feeding_state_reset();
- APPL_TRACE_EVENT2("starting timer %d ticks (%d)", GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TICKS_PER_SEC);
+ APPL_TRACE_EVENT2("starting timer %d ticks (%d)",
+ GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TICKS_PER_SEC);
+
GKI_start_timer(BTIF_MEDIA_AA_TASK_TIMER_ID, GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TRUE);
}
@@ -1790,8 +1819,6 @@
** Returns The number of media frames in this time slice
**
*******************************************************************************/
-
-
static UINT8 btif_get_num_aa_frame(void)
{
UINT8 result=0;
@@ -1886,12 +1913,13 @@
BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id)
{
UINT16 event;
- /* coverity[SIGN_EXTENSION] False-positive: Parameter are always in range avoiding sign extension*/
- UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * btif_media_cb.encoder.s16NumOfBlocks;
+ UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * \
+ btif_media_cb.encoder.s16NumOfBlocks;
UINT32 read_size;
UINT16 sbc_sampling = 48000;
UINT32 src_samples;
- UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * sizeof(SINT16);
+ UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * \
+ sizeof(SINT16);
static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
* SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
static UINT16 read_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
@@ -1992,7 +2020,7 @@
btif_media_cb.media_feeding.cfg.pcm.num_channel);
/* re-sample read buffer */
- /* The output PCM buffer will be stereo, 16 bit per sec */
+ /* The output PCM buffer will be stereo, 16 bit per sample */
dst_size_used = bta_av_sbc_up_sample((UINT8 *)read_buffer,
(UINT8 *)up_sampled_buffer + btif_media_cb.media_feeding_state.pcm.aa_feed_residue,
nb_byte_read,
@@ -2000,7 +2028,7 @@
&src_size_used);
#if (defined(DEBUG_MEDIA_AV_FLOW) && (DEBUG_MEDIA_AV_FLOW == TRUE))
- APPL_TRACE_DEBUG3("btif_media_aa_read_feeding read_size:%d src_size_used:%d dst_size_used:%d",
+ APPL_TRACE_DEBUG3("btif_media_aa_read_feeding readsz:%d src_size_used:%d dst_size_used:%d",
read_size, src_size_used, dst_size_used);
#endif
@@ -2046,16 +2074,19 @@
static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame)
{
BT_HDR * p_buf;
- UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * btif_media_cb.encoder.s16NumOfBlocks;
+ UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands *
+ btif_media_cb.encoder.s16NumOfBlocks;
#if (defined(DEBUG_MEDIA_AV_FLOW) && (DEBUG_MEDIA_AV_FLOW == TRUE))
- APPL_TRACE_DEBUG2("btif_media_aa_prep_sbc_2_send nb_frame %d, TxAaQ %d", nb_frame, btif_media_cb.TxAaQ.count);
+ APPL_TRACE_DEBUG2("btif_media_aa_prep_sbc_2_send nb_frame %d, TxAaQ %d",
+ nb_frame, btif_media_cb.TxAaQ.count);
#endif
while (nb_frame)
{
if (NULL == (p_buf = GKI_getpoolbuf(BTIF_MEDIA_AA_POOL_ID)))
{
- APPL_TRACE_ERROR1 ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ", btif_media_cb.TxAaQ.count);
+ APPL_TRACE_ERROR1 ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ",
+ btif_media_cb.TxAaQ.count);
return;
}
@@ -2069,7 +2100,6 @@
/* Write @ of allocated buffer in encoder.pu8Packet */
btif_media_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
/* Fill allocated buffer with 0 */
- /* coverity[SIGN_EXTENSION] False-positive: Parameter are always in range avoiding sign extension*/
memset(btif_media_cb.encoder.as16PcmBuffer, 0, blocm_x_subband
* btif_media_cb.encoder.s16NumOfChannels);
@@ -2100,11 +2130,12 @@
if(p_buf->len)
{
- btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
-
- /* store the time stamp in the buffer to send */
+ /* timestamp of the media packet header represent the TS of the first SBC frame
+ i.e the timestamp before including this frame */
*((UINT32 *) (p_buf + 1)) = btif_media_cb.timestamp;
+ btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
+
VERBOSE("TX QUEUE NOW %d", btif_media_cb.TxAaQ.count);
if (btif_media_cb.tx_flush)