Merge "Add an override for entering sniff mode after idle on FTS and OTP" into lmp-dev
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index a1a49f3..50a2258 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -459,6 +459,7 @@
     else
     {
         bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
+        bta_dm_cb.disable_timer.param = 0;
         bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
     }
 
@@ -481,11 +482,12 @@
     UNUSED(p_tle);
     UINT8 i;
     tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+    BOOLEAN trigger_disc = FALSE;
 
 
-    APPL_TRACE_EVENT(" bta_dm_disable_timer_cback  ");
+    APPL_TRACE_EVENT(" bta_dm_disable_timer_cback trial %d ", p_tle->param);
 
-    if(BTM_GetNumAclLinks())
+    if(BTM_GetNumAclLinks() && p_tle->param == 0)
     {
         for(i=0; i<bta_dm_cb.device_list.count; i++)
         {
@@ -493,8 +495,17 @@
             transport = bta_dm_cb.device_list.peer_device[i].transport;
 #endif
             btm_remove_acl(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, transport);
+            trigger_disc = TRUE;
         }
 
+        /* Retrigger disable timer in case ACL disconnect failed, DISABLE_EVT still need
+            to be sent out to avoid jave layer disable timeout */
+        if (trigger_disc)
+        {
+            bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
+            bta_dm_cb.disable_timer.param = 1;
+            bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1500);
+        }
     }
     else
     {
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 12262b2..701f6a6 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -2544,13 +2544,18 @@
 void BTA_VendorCleanup (void)
 {
     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
 
 #if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
-    btm_ble_adv_filter_cleanup();
-    btm_ble_vendor_cleanup();
-#endif
+    if (cmn_ble_vsc_cb.max_filter > 0)
+    {
+        btm_ble_adv_filter_cleanup();
+        btm_ble_vendor_cleanup();
+    }
 
-   BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+    if (cmn_ble_vsc_cb.tot_scan_results_strg > 0)
+        btm_ble_batchscan_cleanup();
+#endif
 
    if(cmn_ble_vsc_cb.adv_inst_max > 0)
       btm_ble_multi_adv_cleanup();
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index 4399153..8f3a974 100644
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -562,13 +562,8 @@
             break;
 
         case BTIF_AV_START_STREAM_REQ_EVT:
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
-            {
-                BTA_AvStart();
-                btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
-                break;
-            }
-            btif_a2dp_setup_codec();
+            if (btif_av_cb.peer_sep != AVDT_TSEP_SRC)
+                btif_a2dp_setup_codec();
             BTA_AvStart();
             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
             break;
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index a4347e7..d85867f 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -598,9 +598,9 @@
     int addr_type;
     bdstr_t bdstr;
     bd2str(bd_addr, &bdstr);
-    if(btif_config_get_int("Remote", (char const *)&bdstr,"DevType", &device_type) &&
+    if((btif_config_get_int("Remote", (char const *)&bdstr,"DevType", &device_type) &&
        (btif_storage_get_remote_addr_type(bd_addr, &addr_type) == BT_STATUS_SUCCESS) &&
-       (device_type == BT_DEVICE_TYPE_BLE))
+       (device_type == BT_DEVICE_TYPE_BLE)) || (transport == BT_TRANSPORT_LE))
     {
         BTA_DmAddBleDevice(bd_addr->address, addr_type, BT_DEVICE_TYPE_BLE);
     }
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 2c0a3d1..3a27447 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -732,7 +732,7 @@
             btgatt_batch_track_cb_t *p_data = (btgatt_batch_track_cb_t*) p_param;
             uint8_t *p_rep_data = NULL;
 
-            if (p_data->read_reports.data_len > 0)
+            if (p_data->read_reports.data_len > 0 && NULL != p_data->read_reports.p_rep_data)
             {
                 p_rep_data = GKI_getbuf(p_data->read_reports.data_len);
                 memcpy(p_rep_data, p_data->read_reports.p_rep_data, p_data->read_reports.data_len);
@@ -741,6 +741,8 @@
             HAL_CBACK(bt_gatt_callbacks, client->batchscan_reports_cb
                     , p_data->client_if, p_data->status, p_data->read_reports.report_format
                     , p_data->read_reports.num_records, p_data->read_reports.data_len, p_rep_data);
+            if (NULL != p_rep_data)
+                GKI_freebuf(p_rep_data);
             break;
         }
 
@@ -926,6 +928,7 @@
                                             UINT8* p_rep_data, tBTA_STATUS status)
 {
     btgatt_batch_track_cb_t btif_scan_track_cb;
+    memset(&btif_scan_track_cb, 0, sizeof(btgatt_batch_track_cb_t));
     BTIF_TRACE_DEBUG("%s - client_if:%d, %d, %d, %d",__FUNCTION__, ref_value, status, num_records,
                                     data_len);
 
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 01d5290..7338946 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -510,8 +510,11 @@
 
                 /* post start event and wait for audio path to open */
                 btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
-//FIXME
-                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+
+#if (BTA_AV_SINK_INCLUDED == TRUE)
+                if (btif_media_cb.peer_sep == AVDT_TSEP_SRC)
+                    a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+#endif
             }
             else if (btif_av_stream_started_ready())
             {
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index ae395ba..32ae984 100644
--- a/btif/src/btif_pan.c
+++ b/btif/src/btif_pan.c
@@ -428,6 +428,8 @@
     BTM_GetLocalDeviceAddr (local_addr);
     if(tap_if_up(TAP_IF_NAME, local_addr) == 0)
     {
+        int flags = fcntl(fd, F_GETFL, 0);
+        fcntl(fd, F_SETFL, flags | O_NONBLOCK);
         return fd;
     }
     BTIF_TRACE_ERROR("can not bring up tap interface:%s", TAP_IF_NAME);
@@ -678,8 +680,10 @@
     if (fd == -1 || fd != btpan_cb.tap_fd)
         return;
 
-    // Keep sending until someone either turns off BTIF or disables data the flow.
-    while (btif_is_enabled() && btpan_cb.flow) {
+    // Don't occupy BTU context too long, avoid GKI buffer overruns and
+    // give other profiles a chance to run by limiting the amount of memory
+    // PAN can use from the shared pool buffer.
+    for(int i = 0; i < PAN_POOL_MAX && btif_is_enabled() && btpan_cb.flow; i++) {
         BT_HDR *buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID);
         if (!buffer) {
             BTIF_TRACE_WARNING("%s unable to allocate buffer for packet.", __func__);
diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c
index b234e52..d934c52 100644
--- a/btif/src/btif_sock_rfc.c
+++ b/btif/src/btif_sock_rfc.c
@@ -343,8 +343,13 @@
         BTA_JvCreateRecordByUser((void *)(intptr_t)rs->id);
         *sock_fd = rs->app_fd;
         rs->app_fd = -1; //the fd ownership is transferred to app
-        status = BT_STATUS_SUCCESS;
-        btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, rs->id);
+        if (btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, rs->id)) {
+            status = BT_STATUS_SUCCESS;
+        }
+        else
+        {
+            cleanup_rfc_slot(rs);
+        }
     }
     unlock_slot(&slot_lock);
     return status;
diff --git a/gki/common/gki_time.c b/gki/common/gki_time.c
index b5fe7e2..aa95195 100644
--- a/gki/common/gki_time.c
+++ b/gki/common/gki_time.c
@@ -704,9 +704,6 @@
     if (p_tle == NULL || p_timer_listq->p_first == NULL)
         return FALSE;
 
-    p_tle->ticks = 0;
-    p_tle->in_use = FALSE;
-
     /* Add the ticks remaining in this timer (if any) to the next guy in the list.
     ** Note: Expired timers have a tick value of '0'.
     */
@@ -715,6 +712,9 @@
         p_tle->p_next->ticks += p_tle->ticks;
     }
 
+    p_tle->ticks = 0;
+    p_tle->in_use = FALSE;
+
     /* Unlink timer from the list.
     */
     if (p_timer_listq->p_first == p_tle)
diff --git a/hci/src/userial.c b/hci/src/userial.c
index 4c2a8db..34de045 100644
--- a/hci/src/userial.c
+++ b/hci/src/userial.c
@@ -281,9 +281,12 @@
 
     // Call in to the vendor-specific library to open the serial port.
     int fd_array[CH_MAX];
+    for (int i = 0; i < CH_MAX; i++)
+        fd_array[i] = -1;
+
     int num_ports = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &fd_array);
 
-    if (num_ports > 1) {
+    if (num_ports != 1) {
         ALOGE("%s opened wrong number of ports: got %d, expected 1.", __func__, num_ports);
         goto error;
     }
diff --git a/include/bt_target.h b/include/bt_target.h
index 8c2e200..4239cc7 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -539,6 +539,8 @@
 
 #ifndef PAN_POOL_ID
 #define PAN_POOL_ID                 GKI_POOL_ID_3
+/* Maximum amount of the shared buffer to allocate for PAN */
+#define PAN_POOL_MAX                (GKI_BUF3_MAX / 4)
 #endif
 
 /* UNV pool for read/write serialization */
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
old mode 100644
new mode 100755
index 8feccde..b9ccb48
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -2938,7 +2938,11 @@
 tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb)
 {
     tACL_CONN   *p;
-
+    tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+#if BLE_INCLUDED == TRUE
+    tBT_DEVICE_TYPE dev_type;
+    tBLE_ADDR_TYPE  addr_type;
+#endif
     BTM_TRACE_API ("BTM_ReadRSSI: RemBdAddr: %02x%02x%02x%02x%02x%02x",
                     remote_bda[0], remote_bda[1], remote_bda[2],
                     remote_bda[3], remote_bda[4], remote_bda[5]);
@@ -2947,7 +2951,13 @@
     if (btm_cb.devcb.p_rssi_cmpl_cb)
         return(BTM_BUSY);
 
-    p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
+#if BLE_INCLUDED == TRUE
+    BTM_ReadDevInfo(remote_bda, &dev_type, &addr_type);
+    if (dev_type == BT_DEVICE_TYPE_BLE)
+        transport = BT_TRANSPORT_LE;
+#endif
+
+    p = btm_bda_to_acl(remote_bda, transport);
     if (p != (tACL_CONN *)NULL)
     {
         btu_start_timer (&btm_cb.devcb.rssi_timer, BTU_TTYPE_BTM_ACL,
diff --git a/stack/btm/btm_ble_batchscan.c b/stack/btm/btm_ble_batchscan.c
index 3b7dda7..7ae4b1e 100644
--- a/stack/btm/btm_ble_batchscan.c
+++ b/stack/btm/btm_ble_batchscan.c
@@ -48,7 +48,7 @@
 **  Local functions
 *******************************************************************************/
 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params);
-
+void btm_ble_batchscan_cleanup(void);
 
 /*******************************************************************************
 **
@@ -172,7 +172,6 @@
     {
         len = ble_batchscan_cb.main_rep_q.data_len[index];
         p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index];
-
         if (NULL != p_orig_data)
         {
             p_app_data = GKI_getbuf(len + data_len);
@@ -180,16 +179,17 @@
             memcpy(p_app_data+len, p_data, data_len);
             GKI_freebuf(p_orig_data);
             ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
+            ble_batchscan_cb.main_rep_q.num_records[index] += num_records;
+            ble_batchscan_cb.main_rep_q.data_len[index] += data_len;
         }
         else
         {
             p_app_data = GKI_getbuf(data_len);
             memcpy(p_app_data, p_data, data_len);
             ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
+            ble_batchscan_cb.main_rep_q.num_records[index] = num_records;
+            ble_batchscan_cb.main_rep_q.data_len[index] = data_len;
         }
-
-        ble_batchscan_cb.main_rep_q.num_records[index] += num_records;
-        ble_batchscan_cb.main_rep_q.data_len[index] += data_len;
     }
 }
 
@@ -361,38 +361,8 @@
                  ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
              }
 
-             if (BTM_SUCCESS == status && BTM_BLE_SCAN_DISABLE_CALLED == cur_state)
-                ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE;
-             else
-             if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state)
-             {
-                BTM_TRACE_ERROR("SCAN_ENB_DISAB_CUST_FEATURE - Invalid state after disabled");
-                ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
-             }
              BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d",
                                 status, ble_batchscan_cb.cur_state, cb_evt);
-            /* Clear the queues here */
-            if(BTM_SUCCESS == status && BTM_BLE_SCAN_DISABLE_CALLED == cur_state)
-            {
-                for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
-                {
-                    ble_batchscan_cb.main_rep_q.rep_mode[index] = 0;
-                    if (NULL != ble_batchscan_cb.main_rep_q.p_data[index])
-                        GKI_freebuf(ble_batchscan_cb.main_rep_q.p_data[index]);
-                    ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
-                    ble_batchscan_cb.main_rep_q.ref_value[index] = 0;
-                    ble_batchscan_cb.main_rep_q.num_records[index] = 0;
-                }
-
-                for (index = 0; index < BTM_BLE_BATCH_SCAN_MAX; index++)
-                {
-                    ble_batchscan_cb.op_q.sub_code[index] = 0;
-                    ble_batchscan_cb.op_q.ref_value[index] = 0;
-                    ble_batchscan_cb.op_q.cur_state[index] = 0;
-                }
-                ble_batchscan_cb.op_q.pending_idx = 0;
-                ble_batchscan_cb.op_q.next_idx = 0;
-            }
 
              if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
                 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
@@ -411,6 +381,20 @@
         case BTM_BLE_BATCH_SCAN_SET_PARAMS:
         {
             BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt);
+
+            if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state)
+            {
+                if (BTM_SUCCESS == status)
+                {
+                    ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE;
+                }
+                else
+                {
+                    BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled");
+                    ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
+                }
+            }
+
             if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
                ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
             break;
@@ -555,31 +539,43 @@
 ** Returns          status
 **
 *******************************************************************************/
-tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN enable_disable)
+tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable)
 {
     tBTM_STATUS     status = BTM_NO_RESOURCES;
-    UINT8 enb_disble = 0x01;
+    UINT8 shld_enable = 0x01;
     UINT8 enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable;
 
-    if (!enable_disable)
-        enb_disble = 0x00;
+    if (!should_enable)
+        shld_enable = 0x00;
 
-    pp_enable = enable_param;
-    memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN);
-
-    UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
-    UINT8_TO_STREAM (pp_enable, enb_disble);
-
-    if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
-             BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param,
-             btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED)
+    if (should_enable)
     {
-        status = BTM_MODE_UNSUPPORTED;
-        BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
-        return BTM_ILLEGAL_VALUE;
+        pp_enable = enable_param;
+        memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN);
+
+        UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
+        UINT8_TO_STREAM (pp_enable, shld_enable);
+
+        if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF,
+                 BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param,
+                 btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED)
+        {
+            status = BTM_MODE_UNSUPPORTED;
+            BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
+            return BTM_ILLEGAL_VALUE;
+        }
+    }
+    else
+    if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE,
+                   ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window,
+                   ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED)
+    {
+         status = BTM_MODE_UNSUPPORTED;
+         BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
+         return BTM_ILLEGAL_VALUE;
     }
 
-    if (enable_disable)
+    if (should_enable)
         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
     else
         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED;
@@ -645,11 +641,12 @@
          BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
          BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state)
     {
-         status = btm_ble_enable_disable_batchscan(TRUE);
+        status = btm_ble_enable_disable_batchscan(TRUE);
         if (BTM_CMD_STARTED != status)
             return status;
-         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
-         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
+
+        ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
+        btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
                                     BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
     }
 
@@ -712,8 +709,8 @@
         && (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule ||
         BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule))
     {
-        if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state
-            || BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
+        if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
+            BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
             BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state)
         {
             status = btm_ble_enable_disable_batchscan(TRUE);
@@ -724,6 +721,10 @@
         }
 
         ble_batchscan_cb.scan_mode = scan_mode;
+        ble_batchscan_cb.scan_interval = scan_interval;
+        ble_batchscan_cb.scan_window = scan_window;
+        ble_batchscan_cb.addr_type = addr_type;
+        ble_batchscan_cb.discard_rule = discard_rule;
         /* This command starts batch scanning, if enabled */
         status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type,
                     discard_rule);
@@ -774,7 +775,7 @@
     if (BTM_CMD_STARTED == status)
     {
        /* The user needs to be provided scan disable event */
-       btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
+       btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS,
                                   BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT,
                                   ref_value);
     }
@@ -821,10 +822,9 @@
     if (0 == read_scan_mode)
         read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS;
 
+    /* Check only for modes, as scan reports can be called after disabling batch scan */
     if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode ||
-        BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode)
-        && (BTM_BLE_SCAN_ENABLED_STATE == ble_batchscan_cb.cur_state ||
-            BTM_BLE_SCAN_ENABLE_CALLED == ble_batchscan_cb.cur_state))
+        BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode))
     {
         status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value);
         if (BTM_SUCCESS == status)
@@ -832,8 +832,8 @@
             status = btm_ble_read_batchscan_reports(scan_mode, ref_value);
             if (BTM_CMD_STARTED != status)
             {
-                    btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value,
-                                                   &num_records, &p_data, &data_len);
+                btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value,
+                                               &num_records, &p_data, &data_len);
             }
         }
     }
@@ -899,4 +899,31 @@
     BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE);
 }
 
+/*******************************************************************************
+**
+** Function         btm_ble_batchscan_cleanup
+**
+** Description      This function cleans the batch scan control block.
+**
+** Parameters       None
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_batchscan_cleanup(void)
+{
+    int index = 0;
+    BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup");
+
+    for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
+    {
+        if (NULL != ble_batchscan_cb.main_rep_q.p_data[index])
+            GKI_freebuf(ble_batchscan_cb.main_rep_q.p_data[index]);
+        ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
+    }
+
+    memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
+    memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
+}
+
 #endif
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index b8e33a2..e8aba02 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -400,6 +400,7 @@
 extern void btm_ble_multi_adv_enb_privacy(BOOLEAN enable);
 extern char btm_ble_map_adv_tx_power(int tx_power_index);
 extern void btm_ble_batchscan_init(void);
+extern void btm_ble_batchscan_cleanup(void);
 extern void btm_ble_adv_filter_init(void);
 extern void btm_ble_adv_filter_cleanup(void);
 extern BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 222ac23..9750b86 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -53,6 +53,7 @@
 #define BTM_BLE_SCAN_MODE_NONE      0xff
 typedef UINT8 tBTM_BLE_SCAN_MODE;
 
+#define BTM_BLE_BATCH_SCAN_MODE_DISABLE 0
 #define BTM_BLE_BATCH_SCAN_MODE_PASS  1
 #define BTM_BLE_BATCH_SCAN_MODE_ACTI  2
 #define BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI 3
@@ -493,6 +494,13 @@
     BTM_BLE_SCAN_DISABLED_STATE=4
 }tBTM_BLE_BATCH_SCAN_STATE;
 
+enum
+{
+    BTM_BLE_DISCARD_OLD_ITEMS,
+    BTM_BLE_DISCARD_LOWER_RSSI_ITEMS
+};
+typedef UINT8 tBTM_BLE_DISCARD_RULE;
+
 typedef struct
 {
     UINT8   sub_code[BTM_BLE_BATCH_SCAN_MAX];
@@ -517,6 +525,10 @@
 {
     tBTM_BLE_BATCH_SCAN_STATE      cur_state;
     tBTM_BLE_BATCH_SCAN_MODE scan_mode;
+    UINT32                  scan_interval;
+    UINT32                  scan_window;
+    tBLE_ADDR_TYPE          addr_type;
+    tBTM_BLE_DISCARD_RULE   discard_rule;
     tBTM_BLE_BATCH_SCAN_OPQ  op_q;
     tBTM_BLE_BATCH_SCAN_REP_Q main_rep_q;
     tBTM_BLE_SCAN_SETUP_CBACK     *p_setup_cback;
@@ -750,13 +762,6 @@
 };
 typedef UINT8   tBTM_BLE_CONN_TYPE;
 
-enum
-{
-    BTM_BLE_DISCARD_OLD_ITEMS,
-    BTM_BLE_DISCARD_LOWER_RSSI_ITEMS
-};
-typedef UINT8 tBTM_BLE_DISCARD_RULE;
-
 typedef void (tBTM_BLE_TRACK_ADV_CBACK)(int filt_index, tBLE_ADDR_TYPE addr_type, BD_ADDR bda,
                                         int adv_state, tBTM_BLE_REF_VALUE ref_value);