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

Commit a0d63a9c authored by Mattias Agren's avatar Mattias Agren Committed by Matthew Xie
Browse files

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
parent f9d22c3c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ void btif_a2dp_setup_codec(void);
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);
+43 −9
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ typedef enum {

#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 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
            /* 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 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
    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;

        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 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
            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 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)

        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 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
            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 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
        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 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data

        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 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data

        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 @@ BOOLEAN btif_av_stream_ready(void)
        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 @@ BOOLEAN btif_av_stream_started_ready(void)
    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 @@ const btav_interface_t *btif_av_get_interface(void)

/*******************************************************************************
**
** 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)
+75 −44
Original line number Diff line number Diff line
@@ -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 @@ static UINT32 a2dp_media_task_stack[(A2DP_MEDIA_TASK_STACK_SIZE + 3) / 4];
#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 @@ typedef struct
} 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 int media_task_running = MEDIA_TASK_STATE_OFF;
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 @@ static void tput_mon(int is_rx, int len, int reset)
    /* 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 @@ static void tput_mon(int is_rx, int len, int reset)

    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 @@ static void a2dp_cmd_acknowledge(int status)
{
    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_open(void)

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)
@@ -868,6 +873,24 @@ void btif_a2dp_on_started(tBTA_AV_START *p_av)
}


/*****************************************************************************
**
** 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
@@ -1182,7 +1205,8 @@ static void btif_media_flush_q(BUFFER_Q *p_q)
 *******************************************************************************/
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 @@ static void btif_media_task_enc_update(BT_HDR *p_msg)
    /* 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 @@ static void btif_media_task_enc_update(BT_HDR *p_msg)
                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 @@ static void btif_media_task_pcm2sbc_init(tBTIF_MEDIA_INIT_AUDIO_FEEDING * p_feed
    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 @@ static void btif_media_task_pcm2sbc_init(tBTIF_MEDIA_INIT_AUDIO_FEEDING * p_feed

    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
@@ -1742,7 +1770,6 @@ 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);


    /* 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 @@ static void btif_media_task_aa_start_tx(void)
    /* 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 @@ static void btif_media_task_aa_stop_tx(void)
 ** 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 @@ BT_HDR *btif_media_aa_readbuf(void)
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 @@ BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id)
            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 @@ BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id)
            &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 @@ BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id)
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 @@ static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame)
            /* 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 @@ static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame)

        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)