Replace timers and btu_task
Replace GKI timers with alarms.
diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h
index ac2048a..79f66c2 100644
--- a/bta/sys/bta_sys.h
+++ b/bta/sys/bta_sys.h
@@ -233,6 +233,7 @@
#endif
BTA_API extern void bta_sys_init(void);
+BTA_API extern void bta_sys_free(void);
BTA_API extern void bta_sys_event(BT_HDR *p_msg);
BTA_API extern void bta_sys_timer_update(void);
BTA_API extern void bta_sys_disable_timers(void);
diff --git a/bta/sys/bta_sys_main.c b/bta/sys/bta_sys_main.c
index 550c0e1..cade1d5 100644
--- a/bta/sys/bta_sys_main.c
+++ b/bta/sys/bta_sys_main.c
@@ -21,9 +21,11 @@
* This is the main implementation file for the BTA system manager.
*
******************************************************************************/
+#include <assert.h>
#define LOG_TAG "bta_sys_main"
#include <cutils/log.h>
+#include "alarm.h"
#include "btm_api.h"
#include "bta_api.h"
#include "bta_sys.h"
@@ -31,6 +33,8 @@
#include "fixed_queue.h"
#include "gki.h"
+#include "hash_functions.h"
+#include "hash_map.h"
#include "ptim.h"
#include <string.h>
#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
@@ -43,6 +47,11 @@
tBTA_SYS_CB bta_sys_cb;
#endif
+fixed_queue_t *btu_bta_alarm_queue;
+static hash_map_t *bta_alarm_hash_map;
+static const size_t BTA_ALARM_HASH_MAP_SIZE = 17;
+static pthread_mutex_t bta_alarm_lock;
+
/* trace level */
/* TODO Bluedroid - Hard-coded trace levels - Needs to be configurable */
UINT8 appl_trace_level = BT_TRACE_LEVEL_WARNING; //APPL_INITIAL_TRACE_LEVEL;
@@ -164,6 +173,13 @@
memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
ptim_init(&bta_sys_cb.ptim_cb, BTA_SYS_TIMER_PERIOD, BTA_TIMER);
+
+ pthread_mutex_init(&bta_alarm_lock, NULL);
+
+ bta_alarm_hash_map = hash_map_new(BTA_ALARM_HASH_MAP_SIZE,
+ hash_function_knuth, NULL,NULL);
+ btu_bta_alarm_queue = fixed_queue_new(SIZE_MAX);
+
bta_sys_cb.task_id = GKI_get_taskid();
appl_trace_level = APPL_INITIAL_TRACE_LEVEL;
@@ -179,6 +195,12 @@
}
+BTA_API void bta_sys_free(void) {
+ fixed_queue_free(btu_bta_alarm_queue, NULL);
+ hash_map_free(bta_alarm_hash_map);
+ pthread_mutex_destroy(&bta_alarm_lock);
+}
+
/*******************************************************************************
**
** Function bta_dm_sm_execute
@@ -601,9 +623,33 @@
** Returns void
**
*******************************************************************************/
-void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
-{
- ptim_start_timer(&bta_sys_cb.ptim_cb, p_tle, type, timeout);
+void bta_alarm_cb(void *data) {
+ assert(data != NULL);
+ TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
+
+ fixed_queue_enqueue(btu_bta_alarm_queue, p_tle);
+}
+
+void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout) {
+ assert(p_tle != NULL);
+
+ // Get the alarm for this p_tle.
+ pthread_mutex_lock(&bta_alarm_lock);
+ if (!hash_map_has_key(bta_alarm_hash_map, p_tle)) {
+ hash_map_set(bta_alarm_hash_map, p_tle, alarm_new());
+ }
+ pthread_mutex_unlock(&bta_alarm_lock);
+
+ alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to create alarm\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
+
+ p_tle->event = type;
+ p_tle->ticks = timeout;
+ alarm_set(alarm, (period_ms_t)GKI_TICKS_TO_MS(timeout), bta_alarm_cb, (void *)p_tle);
}
/*******************************************************************************
@@ -615,9 +661,15 @@
** Returns void
**
*******************************************************************************/
-void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle)
-{
- ptim_stop_timer(&bta_sys_cb.ptim_cb, p_tle);
+void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle) {
+ assert(p_tle != NULL);
+
+ alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Expected alarm was not in bta alarm hash map\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
}
/*******************************************************************************
diff --git a/include/bt_target.h b/include/bt_target.h
index 9f26400..97606d0 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -682,7 +682,7 @@
/* if L2CAP_FCR_INCLUDED is TRUE then it should have 100 millisecond resolution */
/* if none of them is included then QUICK_TIMER_TICKS_PER_SEC is set to 0 to exclude quick timer */
#ifndef QUICK_TIMER_TICKS_PER_SEC
-#define QUICK_TIMER_TICKS_PER_SEC 10 /* 10ms timer */
+#define QUICK_TIMER_TICKS_PER_SEC 10 /* 100ms timer */
#endif
/******************************************************************************
diff --git a/main/bte_main.c b/main/bte_main.c
index 2ae5020..d1f65b2 100755
--- a/main/bte_main.c
+++ b/main/bte_main.c
@@ -27,6 +27,7 @@
#include <cutils/properties.h>
#include <fcntl.h>
#include <hardware/bluetooth.h>
+#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
@@ -41,6 +42,8 @@
#include "bt_utils.h"
#include "fixed_queue.h"
#include "gki.h"
+#include "hash_functions.h"
+#include "hash_map.h"
#include "hci_layer.h"
#include "osi.h"
#include "thread.h"
@@ -92,6 +95,24 @@
// Communication queue between btu_task and hci.
fixed_queue_t *btu_hci_msg_queue;
+// General timer queue.
+fixed_queue_t *btu_general_alarm_queue;
+hash_map_t *btu_general_alarm_hash_map;
+pthread_mutex_t btu_general_alarm_lock;
+static const size_t BTU_GENERAL_ALARM_HASH_MAP_SIZE = 17;
+
+// Oneshot timer queue.
+fixed_queue_t *btu_oneshot_alarm_queue;
+hash_map_t *btu_oneshot_alarm_hash_map;
+pthread_mutex_t btu_oneshot_alarm_lock;
+static const size_t BTU_ONESHOT_ALARM_HASH_MAP_SIZE = 17;
+
+// l2cap timer queue.
+fixed_queue_t *btu_l2cap_alarm_queue;
+hash_map_t *btu_l2cap_alarm_hash_map;
+pthread_mutex_t btu_l2cap_alarm_lock;
+static const size_t BTU_L2CAP_ALARM_HASH_MAP_SIZE = 17;
+
/*******************************************************************************
** Static variables
*******************************************************************************/
@@ -224,6 +245,21 @@
btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);
btu_hci_msg_queue = fixed_queue_new(SIZE_MAX);
+ btu_general_alarm_hash_map = hash_map_new(BTU_GENERAL_ALARM_HASH_MAP_SIZE,
+ hash_function_knuth, NULL,NULL);
+ pthread_mutex_init(&btu_general_alarm_lock, NULL);
+ btu_general_alarm_queue = fixed_queue_new(SIZE_MAX);
+
+ btu_oneshot_alarm_hash_map = hash_map_new(BTU_ONESHOT_ALARM_HASH_MAP_SIZE,
+ hash_function_knuth, NULL,NULL);
+ pthread_mutex_init(&btu_oneshot_alarm_lock, NULL);
+ btu_oneshot_alarm_queue = fixed_queue_new(SIZE_MAX);
+
+ btu_l2cap_alarm_hash_map = hash_map_new(BTU_L2CAP_ALARM_HASH_MAP_SIZE,
+ hash_function_knuth, NULL,NULL);
+ pthread_mutex_init(&btu_l2cap_alarm_lock, NULL);
+ btu_l2cap_alarm_queue = fixed_queue_new(SIZE_MAX);
+
/* Initialize BTE control block */
BTE_StartUp();
@@ -254,6 +290,21 @@
bte_hci_disable();
GKI_destroy_task(BTU_TASK);
+ fixed_queue_free(btu_bta_msg_queue, NULL);
+ fixed_queue_free(btu_hci_msg_queue, NULL);
+
+ hash_map_free(btu_general_alarm_hash_map);
+ pthread_mutex_destroy(&btu_general_alarm_lock);
+ fixed_queue_free(btu_general_alarm_queue, NULL);
+
+ hash_map_free(btu_oneshot_alarm_hash_map);
+ pthread_mutex_destroy(&btu_oneshot_alarm_lock);
+ fixed_queue_free(btu_oneshot_alarm_queue, NULL);
+
+ hash_map_free(btu_l2cap_alarm_hash_map);
+ pthread_mutex_destroy(&btu_l2cap_alarm_lock);
+ fixed_queue_free(btu_l2cap_alarm_queue, NULL);
+
BTE_ShutDown();
}
diff --git a/stack/btu/btu_init.c b/stack/btu/btu_init.c
index e84edd4..c20dd7f 100644
--- a/stack/btu/btu_init.c
+++ b/stack/btu/btu_init.c
@@ -28,6 +28,7 @@
#include "dyn_mem.h"
#include "fixed_queue.h"
+#include "hash_map.h"
#include "btu.h"
#include "btm_int.h"
#include "sdpint.h"
@@ -41,9 +42,7 @@
#endif
#endif
-
extern fixed_queue_t *btu_hci_msg_queue;
-extern fixed_queue_t *btu_bta_msg_queue;
extern void PLATFORM_DisableHciTransport(UINT8 bDisable);
/*****************************************************************************
@@ -136,11 +135,8 @@
while (!GKI_queue_is_empty(&btu_cb.hci_cmd_cb[i].cmd_cmpl_q))
GKI_freebuf(GKI_dequeue(&btu_cb.hci_cmd_cb[i].cmd_cmpl_q));
}
- fixed_queue_free(btu_bta_msg_queue, NULL);
- fixed_queue_free(btu_hci_msg_queue, NULL);
}
-
/*****************************************************************************
**
** Function BTU_AclPktSize
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index 92e9872..764b891 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -28,11 +28,15 @@
*
******************************************************************************/
+#include <assert.h>
+
+#define LOG_TAG "btu_task"
#include <cutils/log.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include "alarm.h"
#include "bt_target.h"
#include "bt_trace.h"
#include "bt_types.h"
@@ -42,6 +46,7 @@
#include "btu.h"
#include "fixed_queue.h"
#include "gki.h"
+#include "hash_map.h"
#include "hcimsgs.h"
#include "l2c_int.h"
#include "btu.h"
@@ -148,10 +153,30 @@
// Communication queue between btu_task and hci.
extern fixed_queue_t *btu_hci_msg_queue;
+// Timer queue between btu_task and bta.
+extern fixed_queue_t *btu_bta_alarm_queue;
+
+// General timer queue.
+extern fixed_queue_t *btu_general_alarm_queue;
+extern hash_map_t *btu_general_alarm_hash_map;
+extern pthread_mutex_t btu_general_alarm_lock;
+
+// Oneshot timer queue.
+extern fixed_queue_t *btu_oneshot_alarm_queue;
+extern hash_map_t *btu_oneshot_alarm_hash_map;
+extern pthread_mutex_t btu_oneshot_alarm_lock;
+
+// l2cap timer queue.
+extern fixed_queue_t *btu_l2cap_alarm_queue;
+extern hash_map_t *btu_l2cap_alarm_hash_map;
+extern pthread_mutex_t btu_l2cap_alarm_lock;
/* Define a function prototype to allow a generic timeout handler */
typedef void (tUSER_TIMEOUT_FUNC) (TIMER_LIST_ENT *p_tle);
+static void btu_l2cap_alarm_process(TIMER_LIST_ENT *p_tle);
+static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle);
+
static void btu_hci_msg_process(BT_HDR *p_msg) {
/* Determine the input message type. */
switch (p_msg->event & BT_EVT_MASK)
@@ -313,159 +338,18 @@
}
-static void btu_timer_process() {
- GKI_update_timer_list (&btu_cb.timer_queue, 1);
-
- while (!GKI_timer_queue_is_empty(&btu_cb.timer_queue)) {
- TIMER_LIST_ENT *p_tle = GKI_timer_getfirst(&btu_cb.timer_queue);
- if (p_tle->ticks != 0)
- break;
-
- GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);
-
- switch (p_tle->event)
- {
- case BTU_TTYPE_BTM_DEV_CTL:
- btm_dev_timeout(p_tle);
- break;
-
- case BTU_TTYPE_BTM_ACL:
- btm_acl_timeout(p_tle);
- break;
-
- case BTU_TTYPE_L2CAP_LINK:
- case BTU_TTYPE_L2CAP_CHNL:
- case BTU_TTYPE_L2CAP_HOLD:
- case BTU_TTYPE_L2CAP_INFO:
- case BTU_TTYPE_L2CAP_FCR_ACK:
-
- l2c_process_timeout (p_tle);
- break;
-
- case BTU_TTYPE_SDP:
- sdp_conn_timeout ((tCONN_CB *)p_tle->param);
- break;
-
- case BTU_TTYPE_BTM_RMT_NAME:
- btm_inq_rmt_name_failed();
- break;
-
-#if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE)
- case BTU_TTYPE_RFCOMM_MFC:
- case BTU_TTYPE_RFCOMM_PORT:
- rfcomm_process_timeout (p_tle);
- break;
-
-#endif /* If defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE */
-
-#if ((defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE))
- case BTU_TTYPE_BNEP:
- bnep_process_timeout(p_tle);
- break;
-#endif
-
-
-#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
- case BTU_TTYPE_AVDT_CCB_RET:
- case BTU_TTYPE_AVDT_CCB_RSP:
- case BTU_TTYPE_AVDT_CCB_IDLE:
- case BTU_TTYPE_AVDT_SCB_TC:
- avdt_process_timeout(p_tle);
- break;
-#endif
-
-#if (defined(OBX_INCLUDED) && OBX_INCLUDED == TRUE)
-#if (defined(OBX_CLIENT_INCLUDED) && OBX_CLIENT_INCLUDED == TRUE)
- case BTU_TTYPE_OBX_CLIENT_TO:
- obx_cl_timeout(p_tle);
- break;
-#endif
-#if (defined(OBX_SERVER_INCLUDED) && OBX_SERVER_INCLUDED == TRUE)
- case BTU_TTYPE_OBX_SERVER_TO:
- obx_sr_timeout(p_tle);
- break;
-
- case BTU_TTYPE_OBX_SVR_SESS_TO:
- obx_sr_sess_timeout(p_tle);
- break;
-#endif
-#endif
-
-#if (defined(SAP_SERVER_INCLUDED) && SAP_SERVER_INCLUDED == TRUE)
- case BTU_TTYPE_SAP_TO:
- sap_process_timeout(p_tle);
- break;
-#endif
-
- case BTU_TTYPE_BTU_CMD_CMPL:
- btu_hcif_cmd_timeout((UINT8)(p_tle->event - BTU_TTYPE_BTU_CMD_CMPL));
- break;
-
-#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
- case BTU_TTYPE_HID_HOST_REPAGE_TO :
- hidh_proc_repage_timeout(p_tle);
- break;
-#endif
-
-#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
- case BTU_TTYPE_BLE_INQUIRY:
- case BTU_TTYPE_BLE_GAP_LIM_DISC:
- case BTU_TTYPE_BLE_RANDOM_ADDR:
- case BTU_TTYPE_BLE_GAP_FAST_ADV:
- case BTU_TTYPE_BLE_OBSERVE:
- btm_ble_timeout(p_tle);
- break;
-
- case BTU_TTYPE_ATT_WAIT_FOR_RSP:
- gatt_rsp_timeout(p_tle);
- break;
-
- case BTU_TTYPE_ATT_WAIT_FOR_IND_ACK:
- gatt_ind_ack_timeout(p_tle);
- break;
-#if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE)
- case BTU_TTYPE_SMP_PAIRING_CMD:
- smp_rsp_timeout(p_tle);
- break;
-#endif
-
-#endif
-
-#if (MCA_INCLUDED == TRUE)
- case BTU_TTYPE_MCA_CCB_RSP:
- mca_process_timeout(p_tle);
- break;
-#endif
- case BTU_TTYPE_USER_FUNC:
- {
- tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
- (*p_uf)(p_tle);
- }
- break;
-
- default:;
- int i = 0;
- BOOLEAN handled = FALSE;
-
- for (; !handled && i < BTU_MAX_REG_TIMER; i++)
- {
- if (btu_cb.timer_reg[i].timer_cb == NULL)
- continue;
- if (btu_cb.timer_reg[i].p_tle == p_tle)
- {
- btu_cb.timer_reg[i].timer_cb(p_tle);
- handled = TRUE;
- }
- }
- break;
+static void btu_bta_alarm_process(TIMER_LIST_ENT *p_tle) {
+ /* call timer callback */
+ if (p_tle->p_cback) {
+ (*p_tle->p_cback)(p_tle);
+ } else if (p_tle->event) {
+ BT_HDR *p_msg;
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) {
+ p_msg->event = p_tle->event;
+ p_msg->layer_specific = 0;
+ bta_sys_sendmsg(p_msg);
}
}
-
- /* if timer list is empty stop periodic GKI timer */
- if (btu_cb.timer_queue.p_first == NULL)
- {
- GKI_stop_timer(TIMER_0);
- }
}
/*******************************************************************************
@@ -483,6 +367,7 @@
{
UINT16 event;
BT_HDR *p_msg;
+ TIMER_LIST_ENT *p_tle;
UINT8 i;
UINT16 mask;
BOOLEAN handled;
@@ -545,69 +430,61 @@
for (;;) {
event = GKI_wait (0xFFFF, 0);
- while ((p_msg = (BT_HDR *)fixed_queue_try_dequeue(btu_hci_msg_queue)) != NULL)
+ // HCI message queue.
+ while (!fixed_queue_is_empty(btu_hci_msg_queue)) {
+ p_msg = (BT_HDR *)fixed_queue_dequeue(btu_hci_msg_queue);
btu_hci_msg_process(p_msg);
+ }
- if (event & TIMER_0_EVT_MASK)
- btu_timer_process();
+ // General alarm queue.
+ while (!fixed_queue_is_empty(btu_general_alarm_queue)) {
+ p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(btu_general_alarm_queue);
+ btu_general_alarm_process(p_tle);
+ }
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
- if (event & TIMER_2_EVT_MASK)
- btu_process_quick_timer_evt();
-#endif
+ // L2CAP alarm queue.
+ while (!fixed_queue_is_empty(btu_l2cap_alarm_queue)) {
+ p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(btu_l2cap_alarm_queue);
+ btu_l2cap_alarm_process(p_tle);
+ }
+#endif // QUICK_TIMER
#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
- while ((p_msg = (BT_HDR *)fixed_queue_try_dequeue(btu_bta_msg_queue)) != NULL)
+ // BTA message queue.
+ while (!fixed_queue_is_empty(btu_bta_msg_queue)) {
+ p_msg = (BT_HDR *)fixed_queue_dequeue(btu_bta_msg_queue);
bta_sys_event(p_msg);
+ }
- if (event & TIMER_1_EVT_MASK)
- bta_sys_timer_update();
+ // BTA timer queue.
+ while (!fixed_queue_is_empty(btu_bta_alarm_queue)) {
+ p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(btu_bta_alarm_queue);
+ btu_bta_alarm_process(p_tle);
+ }
+#endif // BTU_BTA_INCLUDED
+
+ while (!fixed_queue_is_empty(btu_oneshot_alarm_queue)) {
+ p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(btu_oneshot_alarm_queue);
+ switch (p_tle->event) {
+#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
+ case BTU_TTYPE_BLE_RANDOM_ADDR:
+ btm_ble_timeout(p_tle);
+ break;
#endif
- if (event & TIMER_3_EVT_MASK) {
- BTM_TRACE_API("Received oneshot timer event complete");
- if (!GKI_timer_queue_is_empty(&btu_cb.timer_queue_oneshot)) {
- TIMER_LIST_ENT *p_tle = GKI_timer_getfirst(&btu_cb.timer_queue_oneshot);
- INT32 ticks_since_last_update = GKI_timer_ticks_getinitial(GKI_timer_getfirst(&btu_cb.timer_queue_oneshot));
- GKI_update_timer_list(&btu_cb.timer_queue_oneshot, ticks_since_last_update);
- }
-
- while (!GKI_timer_queue_is_empty(&btu_cb.timer_queue_oneshot)) {
- TIMER_LIST_ENT *p_tle = GKI_timer_getfirst(&btu_cb.timer_queue_oneshot);
- if (p_tle->ticks != 0)
+ case BTU_TTYPE_USER_FUNC:
+ {
+ tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
+ (*p_uf)(p_tle);
+ }
break;
- GKI_remove_from_timer_list(&btu_cb.timer_queue_oneshot, p_tle);
-
- switch (p_tle->event) {
-#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
- case BTU_TTYPE_BLE_RANDOM_ADDR:
- btm_ble_timeout(p_tle);
- break;
-#endif
-
- case BTU_TTYPE_USER_FUNC:
- {
- tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
- (*p_uf)(p_tle);
- }
- break;
-
- default:
- // FAIL
- BTM_TRACE_WARNING("Received unexpected oneshot timer event:0x%x\n",
- p_tle->event);
- break;
- }
- }
-
- /* Update GKI timer with new tick value from first timer. */
- if (!GKI_timer_queue_is_empty(&btu_cb.timer_queue_oneshot)) {
- TIMER_LIST_ENT *p_tle = GKI_timer_getfirst(&btu_cb.timer_queue_oneshot);
- if (p_tle->ticks > 0)
- GKI_start_timer(TIMER_3, p_tle->ticks, FALSE);
- } else {
- GKI_stop_timer(TIMER_3);
+ default:
+ // FAIL
+ BTM_TRACE_WARNING("Received unexpected oneshot timer event:0x%x\n",
+ p_tle->event);
+ break;
}
}
@@ -615,6 +492,10 @@
break;
}
+#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
+ bta_sys_free();
+#endif
+
btu_free_core();
return(0);
@@ -631,40 +512,174 @@
** Returns void
**
*******************************************************************************/
-void btu_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
-{
- BT_HDR *p_msg;
- GKI_disable();
- /* if timer list is currently empty, start periodic GKI timer */
- if (btu_cb.timer_queue.p_first == NULL)
- {
- /* if timer starts on other than BTU task */
- if (GKI_get_taskid() != BTU_TASK)
- {
- /* post event to start timer in BTU task */
- if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle) {
+ assert(p_tle != NULL);
+
+ switch (p_tle->event) {
+ case BTU_TTYPE_BTM_DEV_CTL:
+ btm_dev_timeout(p_tle);
+ break;
+
+ case BTU_TTYPE_BTM_ACL:
+ btm_acl_timeout(p_tle);
+ break;
+
+ case BTU_TTYPE_L2CAP_LINK:
+ case BTU_TTYPE_L2CAP_CHNL:
+ case BTU_TTYPE_L2CAP_HOLD:
+ case BTU_TTYPE_L2CAP_INFO:
+ case BTU_TTYPE_L2CAP_FCR_ACK:
+ l2c_process_timeout (p_tle);
+ break;
+
+ case BTU_TTYPE_SDP:
+ sdp_conn_timeout ((tCONN_CB *)p_tle->param);
+ break;
+
+ case BTU_TTYPE_BTM_RMT_NAME:
+ btm_inq_rmt_name_failed();
+ break;
+
+#if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE)
+ case BTU_TTYPE_RFCOMM_MFC:
+ case BTU_TTYPE_RFCOMM_PORT:
+ rfcomm_process_timeout (p_tle);
+ break;
+
+#endif /* If defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE */
+
+#if ((defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE))
+ case BTU_TTYPE_BNEP:
+ bnep_process_timeout(p_tle);
+ break;
+#endif
+
+
+#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
+ case BTU_TTYPE_AVDT_CCB_RET:
+ case BTU_TTYPE_AVDT_CCB_RSP:
+ case BTU_TTYPE_AVDT_CCB_IDLE:
+ case BTU_TTYPE_AVDT_SCB_TC:
+ avdt_process_timeout(p_tle);
+ break;
+#endif
+
+#if (defined(OBX_INCLUDED) && OBX_INCLUDED == TRUE)
+#if (defined(OBX_CLIENT_INCLUDED) && OBX_CLIENT_INCLUDED == TRUE)
+ case BTU_TTYPE_OBX_CLIENT_TO:
+ obx_cl_timeout(p_tle);
+ break;
+#endif
+#if (defined(OBX_SERVER_INCLUDED) && OBX_SERVER_INCLUDED == TRUE)
+ case BTU_TTYPE_OBX_SERVER_TO:
+ obx_sr_timeout(p_tle);
+ break;
+
+ case BTU_TTYPE_OBX_SVR_SESS_TO:
+ obx_sr_sess_timeout(p_tle);
+ break;
+#endif
+#endif
+
+#if (defined(SAP_SERVER_INCLUDED) && SAP_SERVER_INCLUDED == TRUE)
+ case BTU_TTYPE_SAP_TO:
+ sap_process_timeout(p_tle);
+ break;
+#endif
+
+ case BTU_TTYPE_BTU_CMD_CMPL:
+ btu_hcif_cmd_timeout((UINT8)(p_tle->event - BTU_TTYPE_BTU_CMD_CMPL));
+ break;
+
+#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
+ case BTU_TTYPE_HID_HOST_REPAGE_TO :
+ hidh_proc_repage_timeout(p_tle);
+ break;
+#endif
+
+#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
+ case BTU_TTYPE_BLE_INQUIRY:
+ case BTU_TTYPE_BLE_GAP_LIM_DISC:
+ case BTU_TTYPE_BLE_RANDOM_ADDR:
+ case BTU_TTYPE_BLE_GAP_FAST_ADV:
+ case BTU_TTYPE_BLE_OBSERVE:
+ btm_ble_timeout(p_tle);
+ break;
+
+ case BTU_TTYPE_ATT_WAIT_FOR_RSP:
+ gatt_rsp_timeout(p_tle);
+ break;
+
+ case BTU_TTYPE_ATT_WAIT_FOR_IND_ACK:
+ gatt_ind_ack_timeout(p_tle);
+ break;
+#if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE)
+ case BTU_TTYPE_SMP_PAIRING_CMD:
+ smp_rsp_timeout(p_tle);
+ break;
+#endif
+
+#endif
+
+#if (MCA_INCLUDED == TRUE)
+ case BTU_TTYPE_MCA_CCB_RSP:
+ mca_process_timeout(p_tle);
+ break;
+#endif
+ case BTU_TTYPE_USER_FUNC:
{
- p_msg->event = BT_EVT_TO_START_TIMER;
- fixed_queue_enqueue(btu_hci_msg_queue, p_msg);
- // Signal the target thread work is ready.
- GKI_send_event(BTU_TASK, (UINT16)EVENT_MASK(BTU_HCI_RCV_MBOX));
+ tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
+ (*p_uf)(p_tle);
}
- }
- else
- {
- /* Start free running 1 second timer for list management */
- GKI_start_timer (TIMER_0, GKI_SECS_TO_TICKS (1), TRUE);
- }
+ break;
+
+ default:;
+ int i = 0;
+ BOOLEAN handled = FALSE;
+
+ for (; !handled && i < BTU_MAX_REG_TIMER; i++)
+ {
+ if (btu_cb.timer_reg[i].timer_cb == NULL)
+ continue;
+ if (btu_cb.timer_reg[i].p_tle == p_tle)
+ {
+ btu_cb.timer_reg[i].timer_cb(p_tle);
+ handled = TRUE;
+ }
+ }
+ break;
}
+}
- GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);
+void btu_general_alarm_cb(void *data) {
+ assert(data != NULL);
+ TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
- p_tle->event = type;
- p_tle->ticks = timeout;
- p_tle->ticks_initial = timeout;
+ fixed_queue_enqueue(btu_general_alarm_queue, p_tle);
+ GKI_send_event(BTU_TASK, TIMER_0_EVT_MASK);
+}
- GKI_add_to_timer_list (&btu_cb.timer_queue, p_tle);
- GKI_enable();
+void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) {
+ assert(p_tle != NULL);
+
+ // Get the alarm for the timer list entry.
+ pthread_mutex_lock(&btu_general_alarm_lock);
+ if (!hash_map_has_key(btu_general_alarm_hash_map, p_tle)) {
+ hash_map_set(btu_general_alarm_hash_map, p_tle, alarm_new());
+ }
+ pthread_mutex_unlock(&btu_general_alarm_lock);
+
+ alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to create alarm\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
+
+ p_tle->event = type;
+ // NOTE: This value is in seconds but stored in a ticks field.
+ p_tle->ticks = timeout_sec;
+ alarm_set(alarm, (period_ms_t)(timeout_sec * 1000), btu_general_alarm_cb, (void *)p_tle);
}
/*******************************************************************************
@@ -690,33 +705,16 @@
** Returns void
**
*******************************************************************************/
-void btu_stop_timer (TIMER_LIST_ENT *p_tle)
-{
- BT_HDR *p_msg;
- GKI_disable();
- GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);
+void btu_stop_timer(TIMER_LIST_ENT *p_tle) {
+ assert(p_tle != NULL);
- /* if timer is stopped on other than BTU task */
- if (GKI_get_taskid() != BTU_TASK)
- {
- /* post event to stop timer in BTU task */
- if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
- {
- p_msg->event = BT_EVT_TO_STOP_TIMER;
- fixed_queue_enqueue(btu_hci_msg_queue, p_msg);
- // Signal the target thread work is ready.
- GKI_send_event(BTU_TASK, (UINT16)EVENT_MASK(BTU_HCI_RCV_MBOX));
- }
- }
- else
- {
- /* if timer list is empty stop periodic GKI timer */
- if (btu_cb.timer_queue.p_first == NULL)
- {
- GKI_stop_timer(TIMER_0);
- }
- }
- GKI_enable();
+ // Get the alarm for the timer list entry.
+ alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to find expected alarm in hashmap\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
}
#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
@@ -724,49 +722,55 @@
**
** Function btu_start_quick_timer
**
-** Description Start a timer for the specified amount of time.
-** NOTE: The timeout resolution depends on including modules.
-** QUICK_TIMER_TICKS_PER_SEC should be used to convert from
-** time to ticks.
-**
+** Description Start a timer for the specified amount of time in ticks.
**
** Returns void
**
*******************************************************************************/
-void btu_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
-{
- BT_HDR *p_msg;
+static void btu_l2cap_alarm_process(TIMER_LIST_ENT *p_tle) {
+ assert(p_tle != NULL);
- GKI_disable();
- /* if timer list is currently empty, start periodic GKI timer */
- if (btu_cb.quick_timer_queue.p_first == NULL)
- {
- /* script test calls stack API without posting event */
- if (GKI_get_taskid() != BTU_TASK)
- {
- /* post event to start timer in BTU task */
- if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
- {
- p_msg->event = BT_EVT_TO_START_QUICK_TIMER;
- fixed_queue_enqueue(btu_hci_msg_queue, p_msg);
- // Signal the target thread work is ready.
- GKI_send_event(BTU_TASK, (UINT16)EVENT_MASK(BTU_HCI_RCV_MBOX));
- }
- }
- else
- GKI_start_timer(TIMER_2, QUICK_TIMER_TICKS, TRUE);
- }
+ switch (p_tle->event) {
+ case BTU_TTYPE_L2CAP_CHNL: /* monitor or retransmission timer */
+ case BTU_TTYPE_L2CAP_FCR_ACK: /* ack timer */
+ l2c_process_timeout (p_tle);
+ break;
- GKI_remove_from_timer_list (&btu_cb.quick_timer_queue, p_tle);
-
- p_tle->event = type;
- p_tle->ticks = timeout;
- p_tle->ticks_initial = timeout;
-
- GKI_add_to_timer_list (&btu_cb.quick_timer_queue, p_tle);
- GKI_enable();
+ default:
+ break;
+ }
}
+static void btu_l2cap_alarm_cb(void *data) {
+ assert(data != NULL);
+ TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
+
+ fixed_queue_enqueue(btu_l2cap_alarm_queue, p_tle);
+ GKI_send_event(BTU_TASK, TIMER_2_EVT_MASK);
+}
+
+void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ticks) {
+ assert(p_tle != NULL);
+
+ // Get the alarm for the timer list entry.
+ pthread_mutex_lock(&btu_l2cap_alarm_lock);
+ if (!hash_map_has_key(btu_l2cap_alarm_hash_map, p_tle)) {
+ hash_map_set(btu_l2cap_alarm_hash_map, p_tle, alarm_new());
+ }
+ pthread_mutex_unlock(&btu_l2cap_alarm_lock);
+
+ alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to create alarm\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
+
+ p_tle->event = type;
+ p_tle->ticks = timeout_ticks;
+ // The quick timer ticks are 100ms long.
+ alarm_set(alarm, (period_ms_t)(timeout_ticks * 100), btu_l2cap_alarm_cb, (void *)p_tle);
+}
/*******************************************************************************
**
@@ -777,130 +781,65 @@
** Returns void
**
*******************************************************************************/
-void btu_stop_quick_timer (TIMER_LIST_ENT *p_tle)
-{
- GKI_disable();
- GKI_remove_from_timer_list (&btu_cb.quick_timer_queue, p_tle);
+void btu_stop_quick_timer(TIMER_LIST_ENT *p_tle) {
+ assert(p_tle != NULL);
- /* if timer list is empty stop periodic GKI timer */
- if (btu_cb.quick_timer_queue.p_first == NULL)
- {
- GKI_stop_timer(TIMER_2);
- }
- GKI_enable();
-}
-
-/*******************************************************************************
-**
-** Function btu_process_quick_timer_evt
-**
-** Description Process quick timer event
-**
-** Returns void
-**
-*******************************************************************************/
-void btu_process_quick_timer_evt(void)
-{
- process_quick_timer_evt(&btu_cb.quick_timer_queue);
-
- /* if timer list is empty stop periodic GKI timer */
- if (btu_cb.quick_timer_queue.p_first == NULL)
- {
- GKI_stop_timer(TIMER_2);
- }
-}
-
-/*******************************************************************************
-**
-** Function process_quick_timer_evt
-**
-** Description Process quick timer event
-**
-** Returns void
-**
-*******************************************************************************/
-void process_quick_timer_evt(TIMER_LIST_Q *p_tlq)
-{
- TIMER_LIST_ENT *p_tle;
-
- GKI_update_timer_list (p_tlq, 1);
-
- while ((p_tlq->p_first) && (!p_tlq->p_first->ticks))
- {
- p_tle = p_tlq->p_first;
- GKI_remove_from_timer_list (p_tlq, p_tle);
-
- switch (p_tle->event)
- {
- case BTU_TTYPE_L2CAP_CHNL: /* monitor or retransmission timer */
- case BTU_TTYPE_L2CAP_FCR_ACK: /* ack timer */
- l2c_process_timeout (p_tle);
- break;
-
- default:
- break;
- }
- }
+ // Get the alarm for the timer list entry.
+ alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to find expected alarm in hashmap\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
}
#endif /* defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) */
+void btu_oneshot_alarm_cb(void *data) {
+ assert(data != NULL);
+ TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
+
+ btu_stop_timer_oneshot(p_tle);
+
+ fixed_queue_enqueue(btu_oneshot_alarm_queue, p_tle);
+ GKI_send_event(BTU_TASK, TIMER_3_EVT_MASK);
+}
+
/*
* Starts a oneshot timer with a timeout in seconds.
*/
-void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_in_secs) {
- INT32 timeout_in_ticks = GKI_SECS_TO_TICKS(timeout_in_secs);
- BTM_TRACE_DEBUG("Starting oneshot timer type:%d timeout:%ds", type, timeout_in_secs);
- GKI_disable();
- if (GKI_timer_queue_is_empty(&btu_cb.timer_queue_oneshot)) {
- }
+void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) {
+ assert(p_tle != NULL);
- GKI_remove_from_timer_list(&btu_cb.timer_queue_oneshot, p_tle);
+ // Get the alarm for the timer list entry.
+ pthread_mutex_lock(&btu_oneshot_alarm_lock);
+ if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) {
+ hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm_new());
+ }
+ pthread_mutex_unlock(&btu_oneshot_alarm_lock);
- p_tle->event = type;
- p_tle->ticks = timeout_in_ticks;
- p_tle->ticks_initial = timeout_in_ticks;
+ alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to create alarm\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
- GKI_add_to_timer_list(&btu_cb.timer_queue_oneshot, p_tle);
- /* RPC to BTU thread if timer start request from non-BTU task */
- if (GKI_get_taskid() != BTU_TASK) {
- /* post event to start timer in BTU task */
- BTM_TRACE_WARNING("Posting oneshot timer event to btu_task");
- BT_HDR *p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE);
- if (p_msg != NULL) {
- p_msg->event = BT_EVT_TO_START_TIMER_ONESHOT;
- fixed_queue_enqueue(btu_hci_msg_queue, p_msg);
- // Signal the target thread work is ready.
- GKI_send_event(BTU_TASK, (UINT16)EVENT_MASK(BTU_HCI_RCV_MBOX));
- }
- } else {
- TIMER_LIST_ENT *tle = GKI_timer_getfirst(&btu_cb.timer_queue_oneshot);
- GKI_start_timer(TIMER_3, tle->ticks, FALSE);
- }
- GKI_enable();
+ p_tle->event = type;
+ // NOTE: This value is in seconds but stored in a ticks field.
+ p_tle->ticks = timeout_sec;
+ alarm_set(alarm, (period_ms_t)(timeout_sec * 1000), btu_oneshot_alarm_cb, (void *)p_tle);
}
void btu_stop_timer_oneshot(TIMER_LIST_ENT *p_tle) {
- GKI_disable();
- GKI_remove_from_timer_list(&btu_cb.timer_queue_oneshot, p_tle);
+ assert(p_tle != NULL);
- if (GKI_get_taskid() != BTU_TASK) {
- /* post event to stop timer in BTU task */
- BT_HDR *p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE);
- if (p_msg != NULL) {
- p_msg->event = BT_EVT_TO_STOP_TIMER_ONESHOT;
- fixed_queue_enqueue(btu_hci_msg_queue, p_msg);
- // Signal the target thread work is ready.
- GKI_send_event(BTU_TASK, (UINT16)EVENT_MASK(BTU_HCI_RCV_MBOX));
- }
- } else {
- if (GKI_timer_queue_is_empty(&btu_cb.timer_queue_oneshot)) {
- BTM_TRACE_WARNING("Stopping oneshot timer");
- GKI_stop_timer(TIMER_3);
- } else {
- BTM_TRACE_WARNING("Request to stop oneshot timer with non empty queue");
- }
- }
- GKI_enable();
+ // Get the alarm for the timer list entry.
+ alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
+ if (alarm == NULL) {
+ ALOGE("%s Unable to find expected alarm in hashmap\n", __func__);
+ return;
+ }
+ alarm_cancel(alarm);
}
#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)