Merge "Bluetooth: Increasing the size of security service record and Adding null check to avoid exception after l2cap psm assigned"
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index fb1d560..d5fb64c 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -1526,10 +1526,13 @@
     UNUSED(p_data);
 
     p_cb->disabling = TRUE;
-
     bta_av_close_all_rc(p_cb);
 
-    utl_freebuf((void **) &p_cb->p_disc_db);
+    /*Cancel SDP if it had been started. */
+    if(p_cb->p_disc_db) {
+        (void)SDP_CancelServiceSearch (p_cb->p_disc_db);
+        utl_freebuf((void **) &p_cb->p_disc_db);
+    }
 
     /* disable audio/video - de-register all channels,
      * expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index b09c7af..eac4269 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -56,6 +56,15 @@
 #define tBTA_DM_PM_TYPE_QUALIFIER
 #endif
 
+/* Reduce Idle timeout value due to intermediate timer */
+#ifndef BTA_JVS_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_JVS_IDLE_TO_SNIFF_DELAY_MS BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS-BTA_JV_IDLE_TIMEOUT*1000
+#endif
+
+#ifndef BTA_JVC_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_JVC_IDLE_TO_SNIFF_DELAY_MS 5000-BTA_JV_IDLE_TIMEOUT*1000
+#endif
+
 
 const tBTA_DM_CFG bta_dm_cfg =
 {
@@ -284,7 +293,7 @@
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
-      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_JVC_IDLE_TO_SNIFF_DELAY_MS},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
       {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
   }
@@ -303,7 +312,7 @@
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
-      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_JVS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
       {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
   }
diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h
index 2cd0d8e..f269266 100644
--- a/bta/include/bta_jv_api.h
+++ b/bta/include/bta_jv_api.h
@@ -68,6 +68,9 @@
 #define BTA_JV_LAST_SERVICE_ID  BTA_LAST_JV_SERVICE_ID
 #define BTA_JV_NUM_SERVICE_ID   (BTA_LAST_JV_SERVICE_ID - BTA_FIRST_JV_SERVICE_ID + 1)
 
+/* Intermediate Idle timeout(s) for TX/RX*/
+#define BTA_JV_IDLE_TIMEOUT 1
+
 /* Discoverable modes */
 enum
 {
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
index a1a61d6..9b58ba0 100644
--- a/bta/jv/bta_jv_act.c
+++ b/bta/jv/bta_jv_act.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 
 #include "osi/include/allocator.h"
+#include "btu.h"
 #include "bt_types.h"
 #include "gki.h"
 #include "utl.h"
@@ -77,7 +78,6 @@
 static uint32_t fc_next_id;
 static pthread_once_t fc_init_once = PTHREAD_ONCE_INIT;
 
-
 static void fc_init_work(void)
 {
     fc_clients = NULL;
@@ -430,6 +430,13 @@
     /* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */
     if (close_conn)
         bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr);
+
+    if (p_pm_cb->is_idle_timer_started == TRUE)
+    {
+        /* Ensure that timer is stopped */
+        btu_stop_timer (&p_pm_cb->idle_tle);
+        p_pm_cb->is_idle_timer_started = FALSE;
+    }
     p_pm_cb->state = BTA_JV_PM_FREE_ST;
     p_pm_cb->app_id = BTA_JV_PM_ALL;
     p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
@@ -592,6 +599,10 @@
         bta_jv_cb.pm_cb[i].app_id = app_id;
         bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr);
         bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
+        bta_jv_cb.pm_cb[i].is_idle_timer_started = FALSE;
+        bta_jv_cb.pm_cb[i].idle_tle.param = (UINT32) bta_jv_idle_timeout_handler;
+        bta_jv_cb.pm_cb[i].idle_tle.data = (UINT32) &bta_jv_cb.pm_cb[i];
+        APPL_TRACE_DEBUG("bta_jv_alloc_set_pm_profile_cb: %d, PM_cb: %p", i, &bta_jv_cb.pm_cb[i]);
         return &bta_jv_cb.pm_cb[i];
     }
     APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
@@ -1400,7 +1411,7 @@
            evt_data.status = BTA_JV_SUCCESS;
         }
         ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
-        bta_jv_set_pm_conn_state(ls->p_cb->p_pm_cb, BTA_JV_CONN_IDLE);
+        bta_jv_pm_conn_idle(ls->p_cb->p_pm_cb);
     } else {
         /* As this pointer is checked in the API function, this occurs only when the channel is
          * disconnected after the API function is called, but before the message is handled. */
@@ -1464,7 +1475,9 @@
         switch(type)
         {
             case DATA_CO_CALLBACK_TYPE_INCOMING:
+                bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
                 ret = bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
+                bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
                 return ret;
             case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
                 return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf);
@@ -2258,7 +2271,17 @@
 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb)
 {
     if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state))
-        bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+    {
+        tBTM_PM_MODE    mode = BTM_PM_MD_ACTIVE;
+        if (BTM_ReadPowerMode(p_cb->peer_bd_addr, &mode) == BTM_SUCCESS) {
+            if (mode == BTM_PM_MD_SNIFF) {
+                bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+            } else {
+                p_cb->state = BTA_JV_PM_BUSY_ST;
+                APPL_TRACE_DEBUG("bta_jv_pm_conn_busy:power mode: %d", mode);
+            }
+        }
+    }
 }
 
 /*******************************************************************************
@@ -2274,8 +2297,17 @@
  *******************************************************************************/
 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb)
 {
-    if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state))
-        bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
+    if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) {
+        APPL_TRACE_DEBUG("bta_jv_pm_conn_idle, p_cb->is_idle_timer_started: %d, p_cb: %p",
+                p_cb->is_idle_timer_started, p_cb);
+        p_cb->state = BTA_JV_PM_IDLE_ST;
+        if (p_cb->is_idle_timer_started == FALSE) {
+            // start intermediate idle timer for 1s
+            btu_start_timer(&p_cb->idle_tle, BTU_TTYPE_USER_FUNC,
+                    BTA_JV_IDLE_TIMEOUT);
+            p_cb->is_idle_timer_started = TRUE;
+        }
+    }
 }
 
 /*******************************************************************************
@@ -2753,3 +2785,34 @@
     if (t)
         fcclient_free(t);
 }
+
+/*******************************************************************************
+**
+** Function         bta_jv_idle_timeout_handler
+**
+** Description      Bta JV specific idle timeout handler
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_jv_idle_timeout_handler(TIMER_LIST_ENT *tle) {
+    tBTA_JV_PM_CB *p_cb = (tBTA_JV_PM_CB *)tle->data;;
+    APPL_TRACE_DEBUG("%s p_cb: %p", __func__, p_cb);
+
+    if (NULL != p_cb) {
+        p_cb->is_idle_timer_started = FALSE;
+
+        tBTM_PM_MODE    mode = BTM_PM_MD_ACTIVE;
+        if (BTM_ReadPowerMode(p_cb->peer_bd_addr, &mode) == BTM_SUCCESS) {
+            if (mode == BTM_PM_MD_SNIFF) {
+                APPL_TRACE_WARNING("%s: %d", __func__, mode)
+                return;
+            } else {
+                APPL_TRACE_DEBUG("%s: %d", __func__, mode);
+            }
+        }
+        bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
+    }
+}
+
diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h
index eaaa75c..119f291 100644
--- a/bta/jv/bta_jv_int.h
+++ b/bta/jv/bta_jv_int.h
@@ -103,6 +103,8 @@
     UINT8           state;      /* state: see above enum */
     tBTA_JV_PM_ID   app_id;     /* JV app specific id indicating power table to use */
     BD_ADDR         peer_bd_addr;    /* Peer BD address */
+    BOOLEAN         is_idle_timer_started; /* intermediate idle timer running status */
+    TIMER_LIST_ENT  idle_tle; /* intermediate idle timer for paricular scb */
 } tBTA_JV_PM_CB;
 
 enum
@@ -447,5 +449,6 @@
 extern void bta_jv_l2cap_stop_server_le (tBTA_JV_MSG *p_data);
 extern void bta_jv_l2cap_write_fixed (tBTA_JV_MSG *p_data);
 extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data);
+extern void bta_jv_idle_timeout_handler(TIMER_LIST_ENT *tle);
 
 #endif /* BTA_JV_INT_H */
diff --git a/hci/include/hci_internals.h b/hci/include/hci_internals.h
index 6b9fb01..e28de6e 100644
--- a/hci/include/hci_internals.h
+++ b/hci/include/hci_internals.h
@@ -18,6 +18,14 @@
 
 #pragma once
 
+#define REMOVE_EAGER_THREADS TRUE
+
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+#include "allocator.h"
+#include "thread.h"
+#include "reactor.h"
+#endif
+
 // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
 #define HCI_COMMAND_PREAMBLE_SIZE 3
 // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
@@ -26,3 +34,31 @@
 #define HCI_SCO_PREAMBLE_SIZE 3
 // 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
 #define HCI_EVENT_PREAMBLE_SIZE 2
+
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+struct hci_reader_t {
+  int inbound_fd;
+
+  const allocator_t *allocator;
+  size_t buffer_size;
+  uint8_t *data_buffer;
+  int rd_ptr;
+  int wr_ptr;
+
+  thread_t *inbound_read_thread;
+  reactor_object_t *inbound_read_object;
+};
+typedef  struct hci_reader_t hci_reader_t;
+typedef void (*hci_reader_cb)(void *context);
+
+hci_reader_t *hci_reader_new(
+    int fd_to_read,
+    size_t buffer_size,
+    size_t max_buffer_count,
+    thread_t *thread,
+    hci_reader_cb read_cb
+    );
+
+size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t max_size);
+void hci_reader_free(hci_reader_t *reader);
+#endif
diff --git a/hci/src/hci_hal.c b/hci/src/hci_hal.c
index fa526ce..a50d7ea 100644
--- a/hci/src/hci_hal.c
+++ b/hci/src/hci_hal.c
@@ -17,6 +17,14 @@
  ******************************************************************************/
 
 #include "hci_hal.h"
+#include "hci_internals.h"
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+#include <assert.h>
+#include <string.h>
+#include "eager_reader.h"
+#include "osi.h"
+#include "log.h"
+#endif
 
 const hci_hal_t *hci_hal_get_interface() {
 #if HCI_USE_MCT
@@ -26,3 +34,87 @@
 #endif
 }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+void hci_reader_free(hci_reader_t *reader) {
+  if (!reader)
+    return;
+
+  // Only unregister from the input if we actually did register
+  if (reader->inbound_read_object)
+    reactor_unregister(reader->inbound_read_object);
+
+  // Free the current buffer, because it's not in the queue
+  // and won't be freed below
+  if (reader->data_buffer)
+    osi_free(reader->data_buffer);
+
+  osi_free(reader);
+}
+
+hci_reader_t *hci_reader_new(
+    int fd_to_read,
+    size_t buffer_size,
+    size_t max_buffer_count,
+    thread_t *thread,
+    hci_reader_cb read_cb
+    ) {
+
+  assert(fd_to_read != INVALID_FD);
+  assert(buffer_size > 0);
+  assert(max_buffer_count > 0);
+
+
+  hci_reader_t *ret = osi_calloc(sizeof(hci_reader_t));
+  if (!ret) {
+    LOG_ERROR("%s unable to allocate memory for new hci_reader.", __func__);
+    goto error;
+  }
+
+  ret->inbound_fd = fd_to_read;
+
+  ret->data_buffer = osi_calloc(buffer_size);
+  ret->buffer_size = buffer_size;
+  ret->rd_ptr = 0;
+  ret->wr_ptr = 0;
+
+  ret->inbound_read_thread = thread;
+  if (!ret->inbound_read_thread) {
+    LOG_ERROR("%s unable to make reading thread.", __func__);
+    goto error;
+  }
+
+  ret->inbound_read_object = reactor_register(
+      thread_get_reactor(ret->inbound_read_thread),
+      fd_to_read,
+      ret,
+      read_cb,
+      NULL
+      );
+
+  return ret;
+
+error:;
+  hci_reader_free(ret);
+  return NULL;
+}
+
+size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t req_size) {
+  size_t bytes_read = 0;
+  assert(reader != NULL);
+  assert(buffer != NULL);
+
+  // If the caller wants nonblocking behavior, poll to see if we have
+  // any bytes available before reading.
+  if (reader->rd_ptr < reader->wr_ptr) {
+    bytes_read = reader->wr_ptr - reader->rd_ptr;
+    if (bytes_read > req_size)
+      bytes_read = req_size;
+    memcpy(buffer, reader->data_buffer+reader->rd_ptr, bytes_read);
+    reader->rd_ptr += bytes_read;
+  } else {
+    bytes_read = read(reader->inbound_fd, buffer, req_size);
+  }
+
+  return bytes_read;
+}
+#endif
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 332c1a2..d4dc105 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -45,13 +45,23 @@
 static thread_t *thread; // Not owned by us
 
 static int uart_fd;
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static hci_reader_t *uart_stream;
+#else
 static eager_reader_t *uart_stream;
+#endif
 static serial_data_type_t current_data_type;
 static bool stream_has_interpretation;
 static bool stream_corruption_detected;
 static uint8_t stream_corruption_bytes_to_ignore;
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_uart_has_bytes(void *context);
+#else
 static void event_uart_has_bytes(eager_reader_t *reader, void *context);
+#endif
+
+static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read);
 
 // Interface functions
 
@@ -82,20 +92,28 @@
     goto error;
   }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  uart_stream = hci_reader_new(uart_fd, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, thread, event_uart_has_bytes);
+  if (!uart_stream) {
+    LOG_ERROR("%s unable to create hci reader for the uart serial port.", __func__);
+    goto error;
+  }
+#else
   uart_stream = eager_reader_new(uart_fd, &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_single_channel");
   if (!uart_stream) {
     LOG_ERROR("%s unable to create eager reader for the uart serial port.", __func__);
     goto error;
   }
+  eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
+  thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
+#endif
 
   stream_has_interpretation = false;
   stream_corruption_detected = false;
   stream_corruption_bytes_to_ignore = 0;
-  eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
 
   // Raise thread priorities to keep up with audio
   thread_set_priority(thread, HCI_THREAD_PRIORITY);
-  thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
 
   return true;
 
@@ -107,8 +125,12 @@
 
 static void hal_close() {
   LOG_INFO("%s", __func__);
-
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  hci_reader_free(uart_stream);
+#else
   eager_reader_free(uart_stream);
+#endif
+
   vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
   uart_fd = INVALID_FD;
 }
@@ -125,7 +147,11 @@
     return 0;
   }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  return hci_reader_read(uart_stream, buffer, max_size);
+#else
   return eager_reader_read(uart_stream, buffer, max_size, block);
+#endif
 }
 
 static void packet_finished(serial_data_type_t type) {
@@ -134,7 +160,24 @@
   else if (current_data_type != type)
     LOG_ERROR("%s with different type than existing interpretation.", __func__);
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  if (uart_stream->rd_ptr == uart_stream->wr_ptr) {
+    uart_stream->rd_ptr = uart_stream->wr_ptr = 0;
+    stream_has_interpretation = false;
+  } else {
+    uint8_t type_byte;
+    type_byte = uart_stream->data_buffer[uart_stream->rd_ptr++];
+    if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
+      LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__,
+                                                    type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+      return;
+    }
+    current_data_type = type_byte;
+    callbacks->data_ready(current_data_type);
+  }
+#else
   stream_has_interpretation = false;
+#endif
 }
 
 static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
@@ -225,6 +268,33 @@
 }
 
 // See what data is waiting, and notify the upper layer
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_uart_has_bytes(void *context) {
+  uint8_t type_byte;
+  size_t bytes_read;
+  hci_reader_t *reader = (hci_reader_t *) context;
+  bytes_read = read(reader->inbound_fd, reader->data_buffer + reader->wr_ptr, reader->buffer_size - reader->wr_ptr);
+
+  if (bytes_read <= 0)  {
+    LOG_ERROR("%s could not read HCI message type", __func__);
+    return;
+  }
+  reader->wr_ptr += bytes_read;
+  if (!stream_has_interpretation) {
+    type_byte = reader->data_buffer[reader->rd_ptr++];
+
+    if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
+      LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+      return;
+    }
+
+    stream_has_interpretation = true;
+    current_data_type = type_byte;
+  }
+
+  callbacks->data_ready(current_data_type);
+}
+#else
 static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) {
   if (stream_has_interpretation) {
     callbacks->data_ready(current_data_type);
@@ -247,6 +317,7 @@
     current_data_type = type_byte;
   }
 }
+#endif
 
 static const hci_hal_t interface = {
   hal_init,
diff --git a/hci/src/hci_hal_mct.c b/hci/src/hci_hal_mct.c
index adc17c3..2c7a323 100644
--- a/hci/src/hci_hal_mct.c
+++ b/hci/src/hci_hal_mct.c
@@ -45,12 +45,22 @@
 static thread_t *thread; // Not owned by us
 
 static int uart_fds[CH_MAX];
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static hci_reader_t *event_stream;
+static hci_reader_t *acl_stream;
+#else
 static eager_reader_t *event_stream;
 static eager_reader_t *acl_stream;
+#endif
 
 static uint16_t transmit_data_on(int fd, uint8_t *data, uint16_t length);
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_event_stream_has_bytes(void *context);
+static void event_acl_stream_has_bytes(void *context);
+#else
 static void event_event_stream_has_bytes(eager_reader_t *reader, void *context);
 static void event_acl_stream_has_bytes(eager_reader_t *reader, void *context);
+#endif
 
 // Interface functions
 
@@ -97,6 +107,21 @@
     goto error;
   }
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  event_stream = hci_reader_new(uart_fds[CH_EVT], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
+                                                 thread, event_event_stream_has_bytes);
+  if (!event_stream) {
+    LOG_ERROR("%s unable to create hci reader for the event uart serial port.", __func__);
+    goto error;
+  }
+
+  acl_stream = hci_reader_new(uart_fds[CH_ACL_IN], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
+                                                    thread, event_acl_stream_has_bytes);
+  if (!acl_stream) {
+    LOG_ERROR("%s unable to create hci reader for the acl-in uart serial port.", __func__);
+    goto error;
+  }
+#else
   event_stream = eager_reader_new(uart_fds[CH_EVT], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
   if (!event_stream) {
     LOG_ERROR("%s unable to create eager reader for the event uart serial port.", __func__);
@@ -104,7 +129,7 @@
   }
 
   acl_stream = eager_reader_new(uart_fds[CH_ACL_IN], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
-  if (!event_stream) {
+  if (!acl_stream) {
     LOG_ERROR("%s unable to create eager reader for the acl-in uart serial port.", __func__);
     goto error;
   }
@@ -112,6 +137,8 @@
   eager_reader_register(event_stream, thread_get_reactor(thread), event_event_stream_has_bytes, NULL);
   eager_reader_register(acl_stream, thread_get_reactor(thread), event_acl_stream_has_bytes, NULL);
 
+#endif
+
   return true;
 
 error:;
@@ -122,8 +149,14 @@
 static void hal_close() {
   LOG_INFO("%s", __func__);
 
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  hci_reader_free(event_stream);
+  hci_reader_free(acl_stream);
+#else
   eager_reader_free(event_stream);
   eager_reader_free(acl_stream);
+#endif
+
   vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
 
   for (int i = 0; i < CH_MAX; i++)
@@ -156,11 +189,19 @@
 #endif
 
 static size_t read_data(serial_data_type_t type, uint8_t *buffer, size_t max_size, bool block) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  if (type == DATA_TYPE_ACL) {
+    return hci_reader_read(acl_stream, buffer, max_size);
+  } else if (type == DATA_TYPE_EVENT) {
+    return hci_reader_read(event_stream, buffer, max_size);
+  }
+#else
   if (type == DATA_TYPE_ACL) {
     return eager_reader_read(acl_stream, buffer, max_size, block);
   } else if (type == DATA_TYPE_EVENT) {
     return eager_reader_read(event_stream, buffer, max_size, block);
   }
+#endif
 
   LOG_ERROR("%s invalid data type: %d", __func__, type);
   return 0;
@@ -168,6 +209,25 @@
 
 static void packet_finished(UNUSED_ATTR serial_data_type_t type) {
   // not needed by this protocol
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+  hci_reader_t *stream = NULL;
+  if (type == DATA_TYPE_ACL) {
+    stream = acl_stream;
+  } else if (type == DATA_TYPE_EVENT) {
+    stream = event_stream;
+  }
+
+  if(!stream) {
+    LOG_ERROR("%s invalid data type: %d", __func__, type);
+    return;
+  }
+
+  if (stream->rd_ptr == stream->wr_ptr) {
+    stream->rd_ptr = stream->wr_ptr = 0;
+  } else {
+    callbacks->data_ready(type);
+  }
+#endif
 }
 
 static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
@@ -208,14 +268,45 @@
   return transmitted_length;
 }
 
-static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_event_stream_has_bytes(void *context) {
+  size_t bytes_read;
+  hci_reader_t *reader = (hci_reader_t *) context;
+  bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,
+                                    reader->buffer_size - reader->wr_ptr);
+  if (bytes_read <= 0) {
+    LOG_ERROR("%s could not read HCI message type", __func__);
+    return;
+  }
+  reader->wr_ptr += bytes_read;
   callbacks->data_ready(DATA_TYPE_EVENT);
 }
+#else
+static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+   callbacks->data_ready(DATA_TYPE_EVENT);
+}
+#endif
 
-static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_acl_stream_has_bytes(void *context) {
   // No real concept of incoming SCO typed data, just ACL
+  size_t bytes_read;
+  hci_reader_t *reader = (hci_reader_t *) context;
+  bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,
+                                  reader->buffer_size - reader->wr_ptr);
+  if (bytes_read <= 0) {
+    LOG_ERROR("%s could not read HCI message type", __func__);
+    return;
+  }
+  reader->wr_ptr += bytes_read;
   callbacks->data_ready(DATA_TYPE_ACL);
 }
+#else
+static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+   // No real concept of incoming SCO typed data, just ACL
+   callbacks->data_ready(DATA_TYPE_ACL);
+}
+#endif
 
 static const hci_hal_t interface = {
   hal_init,
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index e785f48..dc4351f 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -467,7 +467,6 @@
     LOG_ERROR("%s Unable to create alarm", __func__);
     return;
   }
-  alarm_cancel(alarm);
 
   p_tle->event = type;
   // NOTE: This value is in seconds but stored in a ticks field.
@@ -547,7 +546,6 @@
     LOG_ERROR("%s Unable to create alarm", __func__);
     return;
   }
-  alarm_cancel(alarm);
 
   p_tle->event = type;
   p_tle->ticks = timeout_ticks;
@@ -609,7 +607,6 @@
     LOG_ERROR("%s Unable to create alarm", __func__);
     return;
   }
-  alarm_cancel(alarm);
 
   p_tle->event = type;
   p_tle->in_use = TRUE;
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index 1bac4fa..f8011ae 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -195,6 +195,35 @@
 
 /*******************************************************************************
 **
+** Function         l2c_fcr_restart_timer
+**
+** Description      This function starts the (monitor or retransmission) timer.
+**
+** Returns          -
+**
+*******************************************************************************/
+void l2c_fcr_restart_timer (tL2C_CCB *p_ccb)
+{
+    assert(p_ccb != NULL);
+    UINT32  tout;
+
+    /* The timers which are in milliseconds */
+    if (p_ccb->fcrb.wait_ack)
+    {
+        tout = (UINT32)p_ccb->our_cfg.fcr.mon_tout;
+    }
+    else
+    {
+        tout = (UINT32)p_ccb->our_cfg.fcr.rtrans_tout;
+    }
+
+    /* restart the mentioned timer */
+    btu_start_quick_timer (&p_ccb->fcrb.mon_retrans_timer, BTU_TTYPE_L2CAP_CHNL, tout*QUICK_TIMER_TICKS_PER_SEC/1000);
+}
+
+
+/*******************************************************************************
+**
 ** Function         l2c_fcr_stop_timer
 **
 ** Description      This function stops the (monitor or transmission) timer.
@@ -1000,8 +1029,6 @@
         }
 
         /* If we are still in a wait_ack state, do not mess with the timer */
-        if (!p_ccb->fcrb.wait_ack)
-            l2c_fcr_stop_timer (p_ccb);
 
         /* Check if we need to call the "packet_sent" callback */
         if ( (p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) && (full_sdus_xmitted) )
@@ -1015,8 +1042,13 @@
     }
 
     /* If anything still waiting for ack, restart the timer if it was stopped */
-    if (!GKI_queue_is_empty(&p_fcrb->waiting_for_ack_q))
-        l2c_fcr_start_timer (p_ccb);
+    if(!p_ccb->fcrb.wait_ack) {
+        if (!GKI_queue_is_empty(&p_fcrb->waiting_for_ack_q)) {
+            l2c_fcr_restart_timer (p_ccb);
+        }
+        else
+            l2c_fcr_stop_timer (p_ccb);
+    }
 
     return (TRUE);
 }