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

Commit 30698fa8 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov
Browse files

Refactor the Bluetooth timers

* Updated the alarm API:
  - Existing API alarm_new() is modified to take an alarm name
    as an argument.
  - New API alarm_new_periodic() is used to create a periodic
    alarm.
  - Added new API alarm_is_scheduled() to test whether an alarm is
    scheduled.
  - Existing API alarm_set_periodic() is removed: a periodic
    alarm is created by alarm_new_periodic().
  - Added new API alarm_set_on_queue() to set an alarm whose
    callback is executed on a specific queue.
  - Added new API alarm_register_processing_queue() and
    alarm_unregister_processing_queue() to register/unregister
    a queue and the corresponding thread for alarm processing.
  - Added corresponding unit tests.

* Updated the alarm internals:
  - Added alarm_info_t for collecting alarm-related information
    and statistics.
  - Collect and store alarm-related statistics into alarm_info_t
    per alarm.
  - Include the alarm-related statistics and info into the native
    dumpsys output for Bluetooth.
  - Once an alarm expires, the alarm execution is scheduled for
    processing on another internal alarm-specific thread, not
    on the thread that is maintaining the alarms.
  - Implemented callback execution ordering guarantee among
    timers on the same thread with exactly same timeout values.

* Refactor some of the usage of alarm_set() and simplify the
  code by using alarm_set_on_queue() instead.

* Removed the non_repeating timers wrapper, and use directly
  the alarm mechanism / API.

* Refactored all timer_entry_t timers and replaced them with alarm_t
  timers:
  - Replaced the btu_start_timer() / btu_stop_timer() /
    btu_start_quick_timer() / btu_stop_quick_timer() /
    btu_oneshot_alarm() mechanism with alarm_set_on_queue() and
    alarm_cancel()
  - Removed the whole mechanism around the BTU_TTYPE_* timers.

* Fixed a bug when processing the GATT indication confirmation timer
  expiration (timer tGATT_TCB.conf_timer: b/26610829).

* Renamed and/or split misc. timeout functions, fields, and timers

* Renamed time-related constants and changed the values from seconds
  to milliseconds

* Replaced timer tAVDT_CCB.timer_entry with three mutually exclusive timers:
  idle_ccb_timer, ret_ccb_timer, rsp_ccb_timer
  The reason we are using three timers, is because in the original code
  function avdt_ccb_chk_timer() used the timer type in its logic: it
  would stop the timer only if the type is "idle".

* Removed btm_ble_timeout() and replaced it with multiple timeout
  callback functions (per timer)

* Fix the actual value of the global constant BT_1SEC_TIMEOUT and
  rename it to BT_1SEC_TIMEOUT_MS

* Removed btu_cb and associated timers and events, because they are
  never used.

* Removed unused timers, functions, struct and declarations that are
  not used / needed.

Bug: 26611369
Bug: 26610829

Change-Id: I812c8c31710a5daefc58b01fcf35c353768f390f
parent 5bb6cac6
Loading
Loading
Loading
Loading
+9 −14
Original line number Diff line number Diff line
@@ -430,9 +430,9 @@ void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    bta_ag_at_reinit(&p_scb->at_cb);

    /* stop timers */
    bta_sys_stop_timer(&p_scb->act_timer);
    alarm_cancel(p_scb->ring_timer);
#if (BTM_WBS_INCLUDED == TRUE)
    bta_sys_stop_timer(&p_scb->cn_timer);
    alarm_cancel(p_scb->codec_negotiation_timer);
#endif

    close.hdr.handle = bta_ag_scb_to_idx(p_scb);
@@ -522,13 +522,11 @@ void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)

    bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);

    if (p_scb->conn_service == BTA_AG_HFP)
    {
    if (p_scb->conn_service == BTA_AG_HFP) {
        /* if hfp start timer for service level conn */
        bta_sys_start_timer(&p_scb->act_timer, BTA_AG_SVC_TOUT_EVT, p_bta_ag_cfg->conn_tout);
    }
    else
    {
        bta_sys_start_timer(p_scb->ring_timer, p_bta_ag_cfg->conn_tout,
                            BTA_AG_SVC_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
    } else {
        /* else service level conn is open */
        bta_ag_svc_conn_open(p_scb, p_data);
    }
@@ -567,11 +565,9 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    /* Collision Handling */
    for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
    {
        if ((ag_scb->in_use) && (ag_scb->colli_tmr_on))
        if (ag_scb->in_use && alarm_is_scheduled(ag_scb->collision_timer))
        {
            /* stop collision timer */
            ag_scb->colli_tmr_on = FALSE;
            bta_sys_stop_timer (&ag_scb->colli_timer);
            alarm_cancel(ag_scb->collision_timer);

            if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
            {
@@ -814,8 +810,7 @@ void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
        /* Clear AT+BIA mask from previous SLC if any. */
        p_scb->bia_masked_out = 0;

        /* stop timer */
        bta_sys_stop_timer(&p_scb->act_timer);
        alarm_cancel(p_scb->ring_timer);

        /* call callback */
        evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
+10 −18
Original line number Diff line number Diff line
@@ -41,8 +41,8 @@
**  Constants
*****************************************************************************/

/* ring timeout */
#define BTA_AG_RING_TOUT        5000
/* Ring timeout */
#define BTA_AG_RING_TIMEOUT_MS  (5 * 1000)      /* 5 seconds */

#define BTA_AG_CMD_MAX_VAL      32767  /* Maximum value is signed 16-bit value */

@@ -1249,9 +1249,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,

        case BTA_AG_HF_CMD_BCS:
            bta_ag_send_ok(p_scb);

            /* stop cn timer */
            bta_sys_stop_timer(&p_scb->cn_timer);
            alarm_cancel(p_scb->codec_negotiation_timer);

            switch(int_arg)
            {
@@ -1383,7 +1381,7 @@ void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
            /* if incoming call connected stop ring timer */
            if (p_result->result == BTA_AG_IN_CALL_CONN_RES)
            {
                bta_sys_stop_timer(&p_scb->act_timer);
                alarm_cancel(p_scb->ring_timer);
            }

            if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
@@ -1402,8 +1400,7 @@ void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
            break;

        case BTA_AG_END_CALL_RES:
            /* stop ring timer */
            bta_sys_stop_timer(&p_scb->act_timer);
            alarm_cancel(p_scb->ring_timer);

            /* close sco */
            if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
@@ -1513,8 +1510,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
            break;

        case BTA_AG_IN_CALL_CONN_RES:
            /* stop ring timer */
            bta_sys_stop_timer(&p_scb->act_timer);
            alarm_cancel(p_scb->ring_timer);

            /* if sco not opened and we need to open it, send indicators first
            ** then  open sco.
@@ -1536,8 +1532,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
            break;

        case BTA_AG_IN_CALL_HELD_RES:
            /* stop ring timer */
            bta_sys_stop_timer(&p_scb->act_timer);
            alarm_cancel(p_scb->ring_timer);

            bta_ag_send_call_inds(p_scb, p_result->result);

@@ -1598,8 +1593,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
            break;

        case BTA_AG_END_CALL_RES:
            /* stop ring timer */
            bta_sys_stop_timer(&p_scb->act_timer);
            alarm_cancel(p_scb->ring_timer);

            /* if sco open, close sco then send indicator values */
            if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
@@ -1828,8 +1822,6 @@ void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
    }
#endif

    /* restart ring timer */
    bta_sys_start_timer(&p_scb->act_timer, BTA_AG_RING_TOUT_EVT, BTA_AG_RING_TOUT);
    bta_sys_start_timer(p_scb->ring_timer, BTA_AG_RING_TIMEOUT_MS,
                        BTA_AG_RING_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
}

+17 −17
Original line number Diff line number Diff line
@@ -54,9 +54,9 @@
#define BTA_AG_NUM_SCB          2
#endif

/* Timer to wait for retry in case of collision */
#ifndef BTA_AG_COLLISION_TIMER
#define BTA_AG_COLLISION_TIMER  2000
/* Time to wait for retry in case of collision */
#ifndef BTA_AG_COLLISION_TIMEOUT_MS
#define BTA_AG_COLLISION_TIMEOUT_MS (2 * 1000)          /* 2 seconds */
#endif

/* RFCOMM MTU SIZE */
@@ -105,8 +105,8 @@ enum
    BTA_AG_DISC_OK_EVT,
    BTA_AG_DISC_FAIL_EVT,
    BTA_AG_CI_RX_WRITE_EVT,
    BTA_AG_RING_TOUT_EVT,
    BTA_AG_SVC_TOUT_EVT,
    BTA_AG_RING_TIMEOUT_EVT,
    BTA_AG_SVC_TIMEOUT_EVT,
    BTA_AG_CI_SCO_DATA_EVT,
    BTA_AG_CI_SLC_READY_EVT,
    BTA_AG_MAX_EVT,
@@ -251,7 +251,6 @@ typedef struct
    char                clip[BTA_AG_AT_MAX_LEN+1]; /* number string used for CLIP */
    UINT16              serv_handle[BTA_AG_NUM_IDX]; /* RFCOMM server handles */
    tBTA_AG_AT_CB       at_cb;          /* AT command interpreter */
    timer_entry_t       act_timer;      /* ring timer */
    BD_ADDR             peer_addr;      /* peer bd address */
    tSDP_DISCOVERY_DB   *p_disc_db;     /* pointer to discovery database */
    tBTA_SERVICE_MASK   reg_services;   /* services specified in register API */
@@ -263,15 +262,6 @@ typedef struct
    tBTA_AG_PEER_FEAT   peer_features;  /* peer device features */
    UINT16              peer_version;   /* profile version of peer device */
    UINT16              hsp_version;    /* HSP profile version */
#if (BTM_WBS_INCLUDED == TRUE )
    tBTA_AG_PEER_CODEC  peer_codecs;    /* codecs for eSCO supported by the peer */
    tBTA_AG_PEER_CODEC  sco_codec;      /* codec to be used for eSCO connection */
    tBTA_AG_PEER_CODEC  inuse_codec;    /* codec being used for the current SCO connection */
    BOOLEAN             codec_updated;  /* set to TRUE whenever the app updates codec type */
    BOOLEAN             codec_fallback; /* If sco nego fails for mSBC, fallback to CVSD */
    tBTA_AG_SCO_MSBC_SETTINGS codec_msbc_settings; /* settings to be used for the impending eSCO */
    timer_entry_t       cn_timer;       /* codec negotiation timer */
#endif
    UINT16              sco_idx;        /* SCO handle */
    BOOLEAN             in_use;         /* scb in use */
    BOOLEAN             dealloc;        /* TRUE if service shutting down */
@@ -281,8 +271,6 @@ typedef struct
    BOOLEAN             cmee_enabled;   /* set to TRUE if HF enables CME ERROR reporting */
    BOOLEAN             inband_enabled; /* set to TRUE if inband ring enabled */
    BOOLEAN             svc_conn;       /* set to TRUE when service level connection up */
    timer_entry_t       colli_timer;    /* Collision timer */
    BOOLEAN             colli_tmr_on;   /* TRUE if collision timer is active */
    UINT8               state;          /* state machine state */
    UINT8               conn_service;   /* connected service */
    UINT8               peer_scn;       /* peer scn */
@@ -298,6 +286,18 @@ typedef struct
    UINT8               callheld_ind;   /* CIEV call held indicator value */
    BOOLEAN             retry_with_sco_only; /* indicator to try with SCO only when eSCO fails */
    UINT32              bia_masked_out; /* indicators HF does not want us to send */
    alarm_t             *collision_timer;
    alarm_t             *ring_timer;
#if (BTM_WBS_INCLUDED == TRUE)
    alarm_t             *codec_negotiation_timer;
    tBTA_AG_PEER_CODEC  peer_codecs;    /* codecs for eSCO supported by the peer */
    tBTA_AG_PEER_CODEC  sco_codec;      /* codec to be used for eSCO connection */
    tBTA_AG_PEER_CODEC  inuse_codec;    /* codec being used for the current SCO connection */
    BOOLEAN             codec_updated;  /* set to TRUE whenever the app updates codec type */
    BOOLEAN             codec_fallback; /* If sco nego fails for mSBC, fallback to CVSD */
    tBTA_AG_SCO_MSBC_SETTINGS codec_msbc_settings; /* settings to be used for the impending eSCO */
#endif

} tBTA_AG_SCB;

/* type for sco data */
+29 −54
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@
#define BTA_AG_DEBUG FALSE
#endif

extern fixed_queue_t *btu_bta_alarm_queue;

#if BTA_AG_DEBUG == TRUE
static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result);
static char *bta_ag_state_str(UINT8 state);
@@ -272,29 +274,6 @@ const tBTA_AG_ST_TBL bta_ag_st_tbl[] =
tBTA_AG_CB  bta_ag_cb;
#endif

/*******************************************************************************
**
** Function         bta_ag_timer_cback
**
** Description      AG timer callback.
**
**
** Returns          void
**
*******************************************************************************/
static void bta_ag_timer_cback(void *p)
{
    BT_HDR          *p_buf;
    timer_entry_t   *p_te = (timer_entry_t *) p;

    if ((p_buf = (BT_HDR *) osi_getbuf(sizeof(BT_HDR))) != NULL)
    {
        p_buf->event = p_te->event;
        p_buf->layer_specific = bta_ag_scb_to_idx((tBTA_AG_SCB *) p_te->param);
        bta_sys_sendmsg(p_buf);
    }
}

/*******************************************************************************
**
** Function         bta_ag_scb_alloc
@@ -321,9 +300,11 @@ static tBTA_AG_SCB *bta_ag_scb_alloc(void)
            p_scb->codec_updated = FALSE;
#endif
            /* set up timers */
            p_scb->act_timer.param = p_scb;
            p_scb->act_timer.p_cback = bta_ag_timer_cback;
            p_scb->ring_timer = alarm_new("bta_ag.scb_ring_timer");
            p_scb->collision_timer = alarm_new("bta_ag.scb_collision_timer");
#if (BTM_WBS_INCLUDED == TRUE)
            p_scb->codec_negotiation_timer =
                alarm_new("bta_ag.scb_codec_negotiation_timer");
            /* set eSCO mSBC setting to T2 as the preferred */
            p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
#endif
@@ -358,12 +339,12 @@ void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb)

    APPL_TRACE_DEBUG("bta_ag_scb_dealloc %d", bta_ag_scb_to_idx(p_scb));

    /* stop timers */
    bta_sys_stop_timer(&p_scb->act_timer);
    /* stop and free timers */
    alarm_free(p_scb->ring_timer);
#if (BTM_WBS_INCLUDED == TRUE)
    bta_sys_stop_timer(&p_scb->cn_timer);
    alarm_free(p_scb->codec_negotiation_timer);
#endif
    bta_sys_stop_timer(&p_scb->colli_timer);
    alarm_free(p_scb->collision_timer);

    /* initialize control block */
    memset(p_scb, 0, sizeof(tBTA_AG_SCB));
@@ -568,7 +549,7 @@ tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb)

/*******************************************************************************
**
** Function         bta_ag_colli_timer_cback
** Function         bta_ag_collision_timer_cback
**
** Description      AG connection collision timer callback
**
@@ -576,26 +557,16 @@ tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb)
** Returns          void
**
*******************************************************************************/
static void bta_ag_colli_timer_cback (timer_entry_t *p_te)
static void bta_ag_collision_timer_cback(void *data)
{
    tBTA_AG_SCB *p_scb;
    tBTA_AG_SCB *p_scb = (tBTA_AG_SCB *)data;

    APPL_TRACE_DEBUG ("bta_ag_colli_timer_cback");

    if (p_te)
    {
        p_scb = (tBTA_AG_SCB *)p_te->param;

        if (p_scb)
        {
            p_scb->colli_tmr_on = FALSE;
    APPL_TRACE_DEBUG("%s", __func__);

    /* If the peer haven't opened AG connection     */
    /* we will restart opening process.             */
    bta_ag_resume_open(p_scb);
}
    }
}

/*******************************************************************************
**
@@ -649,13 +620,10 @@ void bta_ag_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
            bta_ag_start_servers(p_scb, p_scb->reg_services);

        /* Start timer to han */
        p_scb->colli_timer.p_cback =
            (timer_callback_t *)&bta_ag_colli_timer_cback;
        p_scb->colli_timer.param = p_scb;
        bta_sys_start_timer(&p_scb->colli_timer, 0, BTA_AG_COLLISION_TIMER);
        p_scb->colli_tmr_on = TRUE;
        alarm_set_on_queue(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
                           bta_ag_collision_timer_cback, p_scb,
                           btu_bta_alarm_queue);
    }

}

/*******************************************************************************
@@ -700,6 +668,13 @@ void bta_ag_resume_open (tBTA_AG_SCB *p_scb)
static void bta_ag_api_enable(tBTA_AG_DATA *p_data)
{
    /* initialize control block */
    for (size_t i = 0; i < BTA_AG_NUM_SCB; i++) {
        alarm_free(bta_ag_cb.scb[i].ring_timer);
#if (BTM_WBS_INCLUDED == TRUE)
        alarm_free(bta_ag_cb.scb[i].codec_negotiation_timer);
#endif
        alarm_free(bta_ag_cb.scb[i].collision_timer);
    }
    memset(&bta_ag_cb, 0, sizeof(tBTA_AG_CB));

    /* store callback function */
@@ -1007,9 +982,9 @@ static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result)
        return "Discovery Failed";
    case BTA_AG_CI_RX_WRITE_EVT:
        return "CI RX Write";
    case BTA_AG_RING_TOUT_EVT:
    case BTA_AG_RING_TIMEOUT_EVT:
        return "Ring Timeout";
    case BTA_AG_SVC_TOUT_EVT:
    case BTA_AG_SVC_TIMEOUT_EVT:
        return "Service Timeout";
    case BTA_AG_API_ENABLE_EVT:
        return "Enable AG";
+17 −20
Original line number Diff line number Diff line
@@ -38,10 +38,13 @@
#define BTA_AG_SCO_DEBUG FALSE
#endif

#ifndef BTA_AG_CODEC_NEGO_TIMEOUT
#define BTA_AG_CODEC_NEGO_TIMEOUT   3000
/* Codec negotiation timeout */
#ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS
#define BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS (3 * 1000)          /* 3 seconds */
#endif

extern fixed_queue_t *btu_bta_alarm_queue;

#if BTA_AG_SCO_DEBUG == TRUE
static char *bta_ag_sco_evt_str(UINT8 event);
static char *bta_ag_sco_state_str(UINT8 state);
@@ -640,7 +643,7 @@ BOOLEAN bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB *p_scb)

/*******************************************************************************
**
** Function         bta_ag_cn_timer_cback
** Function         bta_ag_codec_negotiation_timer_cback
**
** Description
**
@@ -648,24 +651,16 @@ BOOLEAN bta_ag_attempt_msbc_safe_settings(tBTA_AG_SCB *p_scb)
** Returns          void
**
*******************************************************************************/
static void bta_ag_cn_timer_cback (timer_entry_t *p_te)
{
    tBTA_AG_SCB *p_scb;

    if (p_te)
static void bta_ag_codec_negotiation_timer_cback(void *data)
{
        p_scb = (tBTA_AG_SCB *)p_te->param;
    tBTA_AG_SCB *p_scb = (tBTA_AG_SCB *)data;

        if (p_scb)
        {
    /* Announce that codec negotiation failed. */
    bta_ag_sco_codec_nego(p_scb, FALSE);

    /* call app callback */
    bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
}
    }
}

/*******************************************************************************
**
@@ -692,9 +687,11 @@ void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb)
        bta_ag_send_bcs(p_scb, NULL);

        /* Start timer to handle timeout */
        p_scb->cn_timer.p_cback = (timer_callback_t *)&bta_ag_cn_timer_cback;
        p_scb->cn_timer.param = p_scb;
        bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT);
        alarm_set_on_queue(p_scb->codec_negotiation_timer,
                           BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS,
                           bta_ag_codec_negotiation_timer_cback,
                           p_scb,
                           btu_bta_alarm_queue);
    }
    else
    {
Loading