merge in jb-mr2-release history after reset to jb-mr2-dev
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h
old mode 100644
new mode 100755
index b3b72e7..55c88d5
--- a/btif/include/btif_media.h
+++ b/btif/include/btif_media.h
@@ -237,6 +237,7 @@
 void btif_a2dp_on_idle(void);
 void btif_a2dp_on_open(void);
 void btif_a2dp_on_started(tBTA_AV_START *p_av);
+void btif_a2dp_ack_fail(void);
 void btif_a2dp_on_stop_req(void);
 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av);
 void btif_a2dp_on_suspend(void);
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index 074164d..fbbd564 100755
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -62,6 +62,8 @@
 
 #define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
 #define BTIF_AV_FLAG_REMOTE_SUSPEND        0x2
+#define BTIF_AV_FLAG_PENDING_START         0x4
+#define BTIF_AV_FLAG_PENDING_STOP          0x8
 
 /*****************************************************************************
 **  Local type definitions
@@ -401,6 +403,7 @@
             /* wait for audioflinger to stop a2dp */
             break;
 
+        case BTA_AV_STOP_EVT:
         case BTIF_AV_STOP_STREAM_REQ_EVT:
               /* immediately flush any pending tx frames while suspend is pending */
               btif_a2dp_set_tx_flush(TRUE);
@@ -462,15 +465,19 @@
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
+            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
+            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
             btif_media_check_iop_exceptions(btif_av_cb.peer_bda.address);
-            break;
+             break;
 
         case BTIF_SM_EXIT_EVT:
+            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
             break;
 
         case BTIF_AV_START_STREAM_REQ_EVT:
             btif_a2dp_setup_codec();
             BTA_AvStart();
+            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
             break;
 
         case BTA_AV_START_EVT:
@@ -478,6 +485,7 @@
             BTIF_TRACE_EVENT3("BTA_AV_START_EVT status %d, suspending %d, init %d",
                 p_av->start.status, p_av->start.suspending, p_av->start.initiator);
 
+            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
             if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
                 return TRUE;
 
@@ -502,6 +510,9 @@
 
         case BTA_AV_CLOSE_EVT:
 
+            /* avdtp link is closed */
+            btif_a2dp_on_stopped(NULL);
+
             /* inform the application that we are disconnected */
             HAL_CBACK(bt_av_callbacks, connection_state_cb,
                 BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
@@ -509,6 +520,20 @@
             btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
+        case BTA_AV_RECONFIG_EVT:
+            if((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
+                (p_av->reconfig.status == BTA_AV_SUCCESS))
+            {
+               APPL_TRACE_WARNING0("reconfig done BTA_AVstart()");
+               BTA_AvStart();
+            }
+            else if(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)
+            {
+               btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+               btif_a2dp_ack_fail();
+            }
+            break;
+
         CHECK_RC_EVENT(event, p_data);
 
         default:
@@ -551,6 +576,11 @@
         case BTIF_SM_EXIT_EVT:
             break;
 
+        case BTIF_AV_START_STREAM_REQ_EVT:
+            /* we were remotely started, just ack back the local request */
+            btif_a2dp_on_started(NULL);
+            break;
+
         /* fixme -- use suspend = true always to work around issue with BTA AV */
         case BTIF_AV_STOP_STREAM_REQ_EVT:
         case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
@@ -627,6 +657,8 @@
 
         case BTA_AV_STOP_EVT:
 
+            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+
             btif_a2dp_on_stopped(&p_av->suspend);
 
             HAL_CBACK(bt_av_callbacks, audio_state_cb,
@@ -640,6 +672,8 @@
 
         case BTA_AV_CLOSE_EVT:
 
+             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+
             /* avdtp link is closed */
 
             btif_a2dp_on_stopped(NULL);
@@ -854,8 +888,8 @@
         return FALSE;
     }
 
-    /* check if we are remotely suspended */
-    if (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND)
+    /* check if we are remotely suspended or stop is pending */
+    if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP))
         return FALSE;
 
     return (state == BTIF_AV_STATE_OPENED);
@@ -878,9 +912,9 @@
     BTIF_TRACE_DEBUG3("btif_av_stream_started : sm hdl %d, state %d, flags %x",
                 btif_av_cb.sm_handle, state, btif_av_cb.flags);
 
-    /* don't allow media task to start if we are suspending or
-       remotely suspended (not yet changed state) */
-    if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND))
+    /* disallow media task to start if we have pending actions */
+    if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND
+        | BTIF_AV_FLAG_PENDING_STOP))
         return FALSE;
 
     return (state == BTIF_AV_STATE_STARTED);
@@ -958,11 +992,11 @@
 
 /*******************************************************************************
 **
-** Function         btif_av_is_rc_open_without_a2dp
+** Function         btif_av_is_connected
 **
-** Description      Checks if GAVDTP Open notification to app is pending (2 second timer)
+** Description      Checks if av has a connected sink
 **
-** Returns          boolean
+** Returns          BOOLEAN
 **
 *******************************************************************************/
 BOOLEAN btif_av_is_connected(void)
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 200cf06..3c15b27 100755
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -35,6 +35,7 @@
 #include <pthread.h>
 #include <stdint.h>
 #include <sys/time.h>
+#include <errno.h>
 
 #include "bt_target.h"
 #include "gki.h"
@@ -51,11 +52,9 @@
 #include "bta_av_ci.h"
 #include "l2c_api.h"
 
-
 #include "btif_av_co.h"
 #include "btif_media.h"
 
-
 #if (BTA_AV_INCLUDED == TRUE)
 #include "sbc_encoder.h"
 #endif
@@ -166,7 +165,7 @@
 #define BT_MEDIA_TASK A2DP_MEDIA_TASK
 
 #define USEC_PER_SEC 1000000L
-#define TPUT_STATS_INTERVAL_US (1000*1000)
+#define TPUT_STATS_INTERVAL_US (3000*1000)
 
 /*
  * CONGESTION COMPENSATION CTRL ::
@@ -234,11 +233,11 @@
 } tBTIF_MEDIA_CB;
 
 typedef struct {
-    int rx;
-    int rx_tot;
-    int tx;
-    int tx_tot;
-    int ts_prev_us;
+    long long rx;
+    long long rx_tot;
+    long long tx;
+    long long tx_tot;
+    long long ts_prev_us;
 } t_stat;
 
 /*****************************************************************************
@@ -256,6 +255,7 @@
 static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
 static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
 static void btif_a2dp_encoder_update(void);
+const char* dump_media_event(UINT16 event);
 
 /*****************************************************************************
  **  Externs
@@ -286,8 +286,8 @@
     /* only monitor one connection at a time for now */
     static t_stat cur_stat;
     struct timespec now;
-    unsigned int prev_us;
-    unsigned int now_us;
+    unsigned long long prev_us;
+    unsigned long long now_us;
 
     if (reset == TRUE)
     {
@@ -309,14 +309,12 @@
 
     now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
 
-    //APPL_TRACE_DEBUG1("%d us", now_us - cur_stat.ts_prev_us);
-
     if ((now_us - cur_stat.ts_prev_us) < TPUT_STATS_INTERVAL_US)
         return;
 
-    APPL_TRACE_WARNING4("tput rx:%d, tx:%d (kB/s)  (tot : rx %d, tx %d bytes)",
-          (cur_stat.rx)/((now_us - cur_stat.ts_prev_us)/1000),
-          (cur_stat.tx)/((now_us - cur_stat.ts_prev_us)/1000),
+    APPL_TRACE_WARNING4("tput rx:%d, tx:%d (bytes/s)  (tot : rx %d, tx %d bytes)",
+          (cur_stat.rx*1000000)/((now_us - cur_stat.ts_prev_us)),
+          (cur_stat.tx*1000000)/((now_us - cur_stat.ts_prev_us)),
            cur_stat.rx_tot, cur_stat.tx_tot);
 
     /* stats dumped. now reset stats for next interval */
@@ -401,7 +399,8 @@
 {
     UINT8 ack = status;
 
-    APPL_TRACE_EVENT2("## a2dp ack : %s, status %d ##", dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
+    APPL_TRACE_EVENT2("## a2dp ack : %s, status %d ##",
+          dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
 
     /* sanity check */
     if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_NONE)
@@ -838,11 +837,17 @@
 
 void btif_a2dp_on_started(tBTA_AV_START *p_av)
 {
-    tBTIF_AV_MEDIA_FEEDINGS media_feeding;
     tBTIF_STATUS status;
 
     APPL_TRACE_EVENT0("## ON A2DP STARTED ##");
 
+    if (p_av == NULL)
+    {
+        /* ack back a local start request */
+        a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+        return;
+    }
+
     if (p_av->status == BTA_AV_SUCCESS)
     {
         if (p_av->suspending == FALSE)
@@ -870,6 +875,24 @@
 
 /*****************************************************************************
 **
+** Function        btif_a2dp_ack_fail
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+
+void btif_a2dp_ack_fail(void)
+{
+    tBTIF_STATUS status;
+
+    APPL_TRACE_EVENT0("## A2DP_CTRL_ACK_FAILURE ##");
+    a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+}
+
+/*****************************************************************************
+**
 ** Function        btif_a2dp_on_stopped
 **
 ** Description
@@ -1182,7 +1205,8 @@
  *******************************************************************************/
 static void btif_media_task_handle_cmd(BT_HDR *p_msg)
 {
-    VERBOSE("btif_media_task_handle_cmd : %d %s", p_msg->event, dump_media_event(p_msg->event));
+    VERBOSE("btif_media_task_handle_cmd : %d %s", p_msg->event,
+             dump_media_event(p_msg->event));
 
     switch (p_msg->event)
     {
@@ -1467,7 +1491,8 @@
     /* Only update the bitrate and MTU size while timer is running to make sure it has been initialized */
     //if (btif_media_cb.is_tx_timer)
     {
-        btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
+        btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE -
+                                      BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
                 < pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET
                 - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
 
@@ -1533,11 +1558,13 @@
                 s16BitPool = 0;
             }
 
-            APPL_TRACE_EVENT2("bitpool candidate : %d (%d kbps)", s16BitPool, pstrEncParams->u16BitRate);
+            APPL_TRACE_EVENT2("bitpool candidate : %d (%d kbps)",
+                         s16BitPool, pstrEncParams->u16BitRate);
 
             if (s16BitPool > pUpdateAudio->MaxBitPool)
             {
-                APPL_TRACE_WARNING1("btif_media_task_enc_update computed bitpool too large (%d)", s16BitPool);
+                APPL_TRACE_DEBUG1("btif_media_task_enc_update computed bitpool too large (%d)",
+                                    s16BitPool);
                 /* Decrease bitrate */
                 btif_media_cb.encoder.u16BitRate -= BTIF_MEDIA_BITRATE_STEP;
                 /* Record that we have decreased the bitrate */
@@ -1592,7 +1619,6 @@
     APPL_TRACE_DEBUG1("num_channel:%d", p_feeding->feeding.cfg.pcm.num_channel);
     APPL_TRACE_DEBUG1("bit_per_sample:%d", p_feeding->feeding.cfg.pcm.bit_per_sample);
 
-
     /* Check the PCM feeding sampling_freq */
     switch (p_feeding->feeding.cfg.pcm.sampling_freq)
     {
@@ -1639,11 +1665,13 @@
 
     if (reconfig_needed != FALSE)
     {
-        APPL_TRACE_DEBUG0("btif_media_task_pcm2sbc_init calls SBC_Encoder_Init");
-        APPL_TRACE_DEBUG1("btif_media_task_pcm2sbc_init mtu %d", btif_media_cb.TxAaMtuSize);
-        APPL_TRACE_DEBUG6("btif_media_task_pcm2sbc_init ch mode %d, nbsubd %d, nb blk %d, alloc method %d, bit rate %d, Smp freq %d",
-                btif_media_cb.encoder.s16ChannelMode, btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
-                btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, btif_media_cb.encoder.s16SamplingFreq);
+        APPL_TRACE_DEBUG1("btif_media_task_pcm2sbc_init :: mtu %d", btif_media_cb.TxAaMtuSize);
+        APPL_TRACE_DEBUG6("ch mode %d, nbsubd %d, nb %d, alloc %d, rate %d, freq %d",
+                btif_media_cb.encoder.s16ChannelMode,
+                btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
+                btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate,
+                btif_media_cb.encoder.s16SamplingFreq);
+
         SBC_Encoder_Init(&(btif_media_cb.encoder));
     }
     else
@@ -1740,8 +1768,7 @@
 static void btif_media_task_aa_start_tx(void)
 {
     APPL_TRACE_DEBUG2("btif_media_task_aa_start_tx is timer %d, feeding mode %d",
-            btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode);
-
+             btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode);
 
     /* Use a timer to poll the UIPC, get rid of the UIPC call back */
     // UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REG_CBACK, NULL);
@@ -1751,7 +1778,9 @@
     /* Reset the media feeding state */
     btif_media_task_feeding_state_reset();
 
-    APPL_TRACE_EVENT2("starting timer %d ticks (%d)", GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TICKS_PER_SEC);
+    APPL_TRACE_EVENT2("starting timer %d ticks (%d)",
+                  GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TICKS_PER_SEC);
+
     GKI_start_timer(BTIF_MEDIA_AA_TASK_TIMER_ID, GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TRUE);
 }
 
@@ -1790,8 +1819,6 @@
  ** Returns          The number of media frames in this time slice
  **
  *******************************************************************************/
-
-
 static UINT8 btif_get_num_aa_frame(void)
 {
     UINT8 result=0;
@@ -1886,12 +1913,13 @@
 BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id)
 {
     UINT16 event;
-    /* coverity[SIGN_EXTENSION] False-positive: Parameter are always in range avoiding sign extension*/
-    UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * btif_media_cb.encoder.s16NumOfBlocks;
+    UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * \
+                             btif_media_cb.encoder.s16NumOfBlocks;
     UINT32 read_size;
     UINT16 sbc_sampling = 48000;
     UINT32 src_samples;
-    UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * sizeof(SINT16);
+    UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * \
+                          sizeof(SINT16);
     static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
             * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
     static UINT16 read_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
@@ -1992,7 +2020,7 @@
             btif_media_cb.media_feeding.cfg.pcm.num_channel);
 
     /* re-sample read buffer */
-    /* The output PCM buffer will be stereo, 16 bit per sec */
+    /* The output PCM buffer will be stereo, 16 bit per sample */
     dst_size_used = bta_av_sbc_up_sample((UINT8 *)read_buffer,
             (UINT8 *)up_sampled_buffer + btif_media_cb.media_feeding_state.pcm.aa_feed_residue,
             nb_byte_read,
@@ -2000,7 +2028,7 @@
             &src_size_used);
 
 #if (defined(DEBUG_MEDIA_AV_FLOW) && (DEBUG_MEDIA_AV_FLOW == TRUE))
-    APPL_TRACE_DEBUG3("btif_media_aa_read_feeding read_size:%d src_size_used:%d dst_size_used:%d",
+    APPL_TRACE_DEBUG3("btif_media_aa_read_feeding readsz:%d src_size_used:%d dst_size_used:%d",
             read_size, src_size_used, dst_size_used);
 #endif
 
@@ -2046,16 +2074,19 @@
 static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame)
 {
     BT_HDR * p_buf;
-    UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * btif_media_cb.encoder.s16NumOfBlocks;
+    UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands *
+                             btif_media_cb.encoder.s16NumOfBlocks;
 
 #if (defined(DEBUG_MEDIA_AV_FLOW) && (DEBUG_MEDIA_AV_FLOW == TRUE))
-    APPL_TRACE_DEBUG2("btif_media_aa_prep_sbc_2_send nb_frame %d, TxAaQ %d", nb_frame, btif_media_cb.TxAaQ.count);
+    APPL_TRACE_DEBUG2("btif_media_aa_prep_sbc_2_send nb_frame %d, TxAaQ %d",
+                       nb_frame, btif_media_cb.TxAaQ.count);
 #endif
     while (nb_frame)
     {
         if (NULL == (p_buf = GKI_getpoolbuf(BTIF_MEDIA_AA_POOL_ID)))
         {
-            APPL_TRACE_ERROR1 ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ", btif_media_cb.TxAaQ.count);
+            APPL_TRACE_ERROR1 ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ",
+                                btif_media_cb.TxAaQ.count);
             return;
         }
 
@@ -2069,7 +2100,6 @@
             /* Write @ of allocated buffer in encoder.pu8Packet */
             btif_media_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
             /* Fill allocated buffer with 0 */
-            /* coverity[SIGN_EXTENSION] False-positive: Parameter are always in range avoiding sign extension*/
             memset(btif_media_cb.encoder.as16PcmBuffer, 0, blocm_x_subband
                     * btif_media_cb.encoder.s16NumOfChannels);
 
@@ -2100,11 +2130,12 @@
 
         if(p_buf->len)
         {
-            btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
-
-            /* store the time stamp in the buffer to send */
+            /* timestamp of the media packet header represent the TS of the first SBC frame
+               i.e the timestamp before including this frame */
             *((UINT32 *) (p_buf + 1)) = btif_media_cb.timestamp;
 
+            btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
+
             VERBOSE("TX QUEUE NOW %d", btif_media_cb.TxAaQ.count);
 
             if (btif_media_cb.tx_flush)
diff --git a/hci/include/bt_hci_bdroid.h b/hci/include/bt_hci_bdroid.h
index 5681e85..7b23851 100644
--- a/hci/include/bt_hci_bdroid.h
+++ b/hci/include/bt_hci_bdroid.h
@@ -86,6 +86,7 @@
 #define HC_EVENT_LPM_ALLOW_SLEEP       0x0080
 #define HC_EVENT_LPM_IDLE_TIMEOUT      0x0100
 #define HC_EVENT_EXIT                  0x0200
+#define HC_EVENT_EPILOG                0x0400
 
 /* Message event mask across Host/Controller lib and stack */
 #define MSG_EVT_MASK                    0xFF00 /* eq. BT_EVT_MASK */
diff --git a/hci/include/bt_vendor_lib.h b/hci/include/bt_vendor_lib.h
index 054e317..f774a14 100644
--- a/hci/include/bt_vendor_lib.h
+++ b/hci/include/bt_vendor_lib.h
@@ -80,10 +80,10 @@
  *      Typecasting conversion: (int (*)[]) param.
  *  [return]
  *      Numbers of opened file descriptors.
-     *      Valid number:
-     *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
-     *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
-     *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
+ *      Valid number:
+ *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
+ *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
+ *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
  *  [callback]
  *      None.
  */
@@ -141,6 +141,20 @@
  *      None.
  */
     BT_VND_OP_LPM_WAKE_SET_STATE,
+
+/*  [operation]
+ *      The epilog call to the vendor module so that it can perform any
+ *      vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
+ *      before the caller calls for cleanup().
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call epilog_cb to notify the stack of the completion of vendor
+ *      specific epilog process once it has been done.
+ */
+    BT_VND_OP_EPILOG,
 } bt_vendor_opcode_t;
 
 /** Power on/off control states */
@@ -280,6 +294,9 @@
 
     /* hci command packet transmit request */
     cmd_xmit_cb xmit_cb;
+
+    /* notifies caller completion of epilog process */
+    cfg_result_cb epilog_cb;
 } bt_vendor_callbacks_t;
 
 /*
diff --git a/hci/src/bt_hci_bdroid.c b/hci/src/bt_hci_bdroid.c
index 8a04d47..90249aa 100644
--- a/hci/src/bt_hci_bdroid.c
+++ b/hci/src/bt_hci_bdroid.c
@@ -47,6 +47,11 @@
 #define BTHCDBG(param, ...) {}
 #endif
 
+/* Vendor epilog process timeout period  */
+#ifndef EPILOG_TIMEOUT_MS
+#define EPILOG_TIMEOUT_MS 3000  // 3 seconds
+#endif
+
 /******************************************************************************
 **  Externs
 ******************************************************************************/
@@ -81,6 +86,8 @@
     pthread_t       worker_thread;
     pthread_mutex_t mutex;
     pthread_cond_t  cond;
+    uint8_t         epilog_timer_created;
+    timer_t         epilog_timer_id;
 } bt_hc_cb_t;
 
 /******************************************************************************
@@ -106,6 +113,63 @@
     pthread_mutex_unlock(&hc_cb.mutex);
 }
 
+/*******************************************************************************
+**
+** Function        epilog_wait_timeout
+**
+** Description     Timeout thread of epilog watchdog timer
+**
+** Returns         None
+**
+*******************************************************************************/
+static void epilog_wait_timeout(union sigval arg)
+{
+    ALOGI("...epilog_wait_timeout...");
+    bthc_signal_event(HC_EVENT_EXIT);
+}
+
+/*******************************************************************************
+**
+** Function        epilog_wait_timer
+**
+** Description     Launch epilog watchdog timer
+**
+** Returns         None
+**
+*******************************************************************************/
+static void epilog_wait_timer(void)
+{
+    int status;
+    struct itimerspec ts;
+    struct sigevent se;
+    uint32_t timeout_ms = EPILOG_TIMEOUT_MS;
+
+    se.sigev_notify = SIGEV_THREAD;
+    se.sigev_value.sival_ptr = &hc_cb.epilog_timer_id;
+    se.sigev_notify_function = epilog_wait_timeout;
+    se.sigev_notify_attributes = NULL;
+
+    status = timer_create(CLOCK_MONOTONIC, &se, &hc_cb.epilog_timer_id);
+
+    if (status == 0)
+    {
+        hc_cb.epilog_timer_created = 1;
+        ts.it_value.tv_sec = timeout_ms/1000;
+        ts.it_value.tv_nsec = 1000000*(timeout_ms%1000);
+        ts.it_interval.tv_sec = 0;
+        ts.it_interval.tv_nsec = 0;
+
+        status = timer_settime(hc_cb.epilog_timer_id, 0, &ts, 0);
+        if (status == -1)
+            ALOGE("Failed to fire epilog watchdog timer");
+    }
+    else
+    {
+        ALOGE("Failed to create epilog watchdog timer");
+        hc_cb.epilog_timer_created = 0;
+    }
+}
+
 /*****************************************************************************
 **
 **   BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS
@@ -126,6 +190,8 @@
         return BT_HC_STATUS_FAIL;
     }
 
+    hc_cb.epilog_timer_created = 0;
+
     /* store reference to user callbacks */
     bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
 
@@ -295,11 +361,20 @@
 
     if (lib_running)
     {
-        lib_running = 0;
-        bthc_signal_event(HC_EVENT_EXIT);
+        epilog_wait_timer();
+
+        bthc_signal_event(HC_EVENT_EPILOG);
         pthread_join(hc_cb.worker_thread, NULL);
+
+        if (hc_cb.epilog_timer_created == 1)
+        {
+            timer_delete(hc_cb.epilog_timer_id);
+            hc_cb.epilog_timer_created = 0;
+        }
     }
 
+    lib_running = 0;
+
     lpm_cleanup();
     userial_close();
     p_hci_if->cleanup();
@@ -480,11 +555,21 @@
             lpm_wake_assert();
         }
 
+        if (events & HC_EVENT_EPILOG)
+        {
+            /* Calling vendor-specific part */
+            if (bt_vnd_if)
+                bt_vnd_if->op(BT_VND_OP_EPILOG, NULL);
+            else
+                break;  // equivalent to HC_EVENT_EXIT
+        }
+
         if (events & HC_EVENT_EXIT)
             break;
     }
 
     ALOGI("bt_hc_worker_thread exiting");
+    lib_running = 0;
 
     pthread_exit(NULL);
 
diff --git a/hci/src/bt_hw.c b/hci/src/bt_hw.c
index b2a099f..fae296b 100644
--- a/hci/src/bt_hw.c
+++ b/hci/src/bt_hw.c
@@ -162,6 +162,22 @@
     return p_hci_if->send_int_cmd(opcode, (HC_BT_HDR *)p_buf, p_cback);
 }
 
+/******************************************************************************
+**
+** Function         epilog_cb
+**
+** Description      HOST/CONTROLLER VENDOR LIB CALLBACK API - This function is
+**                  called back from the libbt-vendor to indicate the result of
+**                  previous epilog call.
+**
+** Returns          None
+**
+******************************************************************************/
+static void epilog_cb(bt_vendor_op_result_t result)
+{
+    bthc_signal_event(HC_EVENT_EXIT);
+}
+
 /*****************************************************************************
 **   The libbt-vendor Callback Functions Table
 *****************************************************************************/
@@ -172,7 +188,8 @@
     lpm_vnd_cb,
     alloc,
     dealloc,
-    xmit_cb
+    xmit_cb,
+    epilog_cb
 };
 
 /******************************************************************************