Merge "Add LE Audio COD constant definition"
diff --git a/android/app/src/com/android/bluetooth/hid/HidHostService.java b/android/app/src/com/android/bluetooth/hid/HidHostService.java
index e62e74a..f2baa1a 100644
--- a/android/app/src/com/android/bluetooth/hid/HidHostService.java
+++ b/android/app/src/com/android/bluetooth/hid/HidHostService.java
@@ -21,7 +21,6 @@
 import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
 
 import android.annotation.RequiresPermission;
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHidHost;
 import android.bluetooth.BluetoothProfile;
@@ -66,6 +65,7 @@
     private BluetoothDevice mTargetDevice = null;
 
     private DatabaseManager mDatabaseManager;
+    private AdapterService mAdapterService;
 
     private static final int MESSAGE_CONNECT = 1;
     private static final int MESSAGE_DISCONNECT = 2;
@@ -96,6 +96,8 @@
     protected boolean start() {
         mDatabaseManager = Objects.requireNonNull(AdapterService.getAdapterService().getDatabase(),
                 "DatabaseManager cannot be null when HidHostService starts");
+        mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(),
+                "AdapterService cannot be null when HidHostService starts");
 
         mInputDevices = Collections.synchronizedMap(new HashMap<BluetoothDevice, Integer>());
         initializeNative();
@@ -133,6 +135,14 @@
         setHidHostService(null);
     }
 
+    private BluetoothDevice getDevice(byte[] address) {
+        return mAdapterService.getDeviceFromByte(address);
+    }
+
+    private byte[] getByteAddress(BluetoothDevice device) {
+        return mAdapterService.getByteIdentityAddress(device);
+    }
+
     public static synchronized HidHostService getHidHostService() {
         if (sHidHostService == null) {
             Log.w(TAG, "getHidHostService(): service is null");
@@ -161,7 +171,7 @@
             switch (msg.what) {
                 case MESSAGE_CONNECT: {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
-                    if (!connectHidNative(Utils.getByteAddress(device))) {
+                    if (!connectHidNative(getByteAddress(device))) {
                         broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
                         broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
                         break;
@@ -171,7 +181,7 @@
                 break;
                 case MESSAGE_DISCONNECT: {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
-                    if (!disconnectHidNative(Utils.getByteAddress(device))) {
+                    if (!disconnectHidNative(getByteAddress(device))) {
                         broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
                         broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
                         break;
@@ -179,8 +189,7 @@
                 }
                 break;
                 case MESSAGE_CONNECT_STATE_CHANGED: {
-                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
-                            .getRemoteDevice((byte[]) msg.obj);
+                    BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
                     int halState = msg.arg1;
                     Integer prevStateInteger = mInputDevices.get(device);
                     int prevState =
@@ -196,7 +205,7 @@
                         if (DBG) {
                             Log.d(TAG, "Incoming HID connection rejected");
                         }
-                        virtualUnPlugNative(Utils.getByteAddress(device));
+                        virtualUnPlugNative(getByteAddress(device));
                     } else {
                         broadcastConnectionState(device, convertHalState(halState));
                     }
@@ -212,22 +221,21 @@
                 break;
                 case MESSAGE_GET_PROTOCOL_MODE: {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
-                    if (!getProtocolModeNative(Utils.getByteAddress(device))) {
+                    if (!getProtocolModeNative(getByteAddress(device))) {
                         Log.e(TAG, "Error: get protocol mode native returns false");
                     }
                 }
                 break;
 
                 case MESSAGE_ON_GET_PROTOCOL_MODE: {
-                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
-                            .getRemoteDevice((byte[]) msg.obj);
+                    BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
                     int protocolMode = msg.arg1;
                     broadcastProtocolMode(device, protocolMode);
                 }
                 break;
                 case MESSAGE_VIRTUAL_UNPLUG: {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
-                    if (!virtualUnPlugNative(Utils.getByteAddress(device))) {
+                    if (!virtualUnPlugNative(getByteAddress(device))) {
                         Log.e(TAG, "Error: virtual unplug native returns false");
                     }
                 }
@@ -236,7 +244,7 @@
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
                     byte protocolMode = (byte) msg.arg1;
                     Log.d(TAG, "sending set protocol mode(" + protocolMode + ")");
-                    if (!setProtocolModeNative(Utils.getByteAddress(device), protocolMode)) {
+                    if (!setProtocolModeNative(getByteAddress(device), protocolMode)) {
                         Log.e(TAG, "Error: set protocol mode native returns false");
                     }
                 }
@@ -247,15 +255,14 @@
                     byte reportType = data.getByte(BluetoothHidHost.EXTRA_REPORT_TYPE);
                     byte reportId = data.getByte(BluetoothHidHost.EXTRA_REPORT_ID);
                     int bufferSize = data.getInt(BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE);
-                    if (!getReportNative(Utils.getByteAddress(device), reportType, reportId,
+                    if (!getReportNative(getByteAddress(device), reportType, reportId,
                             bufferSize)) {
                         Log.e(TAG, "Error: get report native returns false");
                     }
                 }
                 break;
                 case MESSAGE_ON_GET_REPORT: {
-                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
-                            .getRemoteDevice((byte[]) msg.obj);
+                    BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
                     Bundle data = msg.getData();
                     byte[] report = data.getByteArray(BluetoothHidHost.EXTRA_REPORT);
                     int bufferSize = data.getInt(BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE);
@@ -263,8 +270,7 @@
                 }
                 break;
                 case MESSAGE_ON_HANDSHAKE: {
-                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
-                            .getRemoteDevice((byte[]) msg.obj);
+                    BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
                     int status = msg.arg1;
                     broadcastHandshake(device, status);
                 }
@@ -274,28 +280,26 @@
                     Bundle data = msg.getData();
                     byte reportType = data.getByte(BluetoothHidHost.EXTRA_REPORT_TYPE);
                     String report = data.getString(BluetoothHidHost.EXTRA_REPORT);
-                    if (!setReportNative(Utils.getByteAddress(device), reportType, report)) {
+                    if (!setReportNative(getByteAddress(device), reportType, report)) {
                         Log.e(TAG, "Error: set report native returns false");
                     }
                 }
                 break;
                 case MESSAGE_ON_VIRTUAL_UNPLUG: {
-                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
-                            .getRemoteDevice((byte[]) msg.obj);
+                    BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
                     int status = msg.arg1;
                     broadcastVirtualUnplugStatus(device, status);
                 }
                 break;
                 case MESSAGE_GET_IDLE_TIME: {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
-                    if (!getIdleTimeNative(Utils.getByteAddress(device))) {
+                    if (!getIdleTimeNative(getByteAddress(device))) {
                         Log.e(TAG, "Error: get idle time native returns false");
                     }
                 }
                 break;
                 case MESSAGE_ON_GET_IDLE_TIME: {
-                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
-                            .getRemoteDevice((byte[]) msg.obj);
+                    BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
                     int idleTime = msg.arg1;
                     broadcastIdleTime(device, idleTime);
                 }
@@ -304,7 +308,7 @@
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
                     Bundle data = msg.getData();
                     byte idleTime = data.getByte(BluetoothHidHost.EXTRA_IDLE_TIME);
-                    if (!setIdleTimeNative(Utils.getByteAddress(device), idleTime)) {
+                    if (!setIdleTimeNative(getByteAddress(device), idleTime)) {
                         Log.e(TAG, "Error: get idle time native returns false");
                     }
                 }
@@ -778,7 +782,7 @@
             return false;
         }
 
-        return sendDataNative(Utils.getByteAddress(device), report);
+        return sendDataNative(getByteAddress(device), report);
     }
 
     boolean getIdleTime(BluetoothDevice device) {
diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h
index 9800d50..9987f54 100644
--- a/system/gd/hci/acl_manager/le_impl.h
+++ b/system/gd/hci/acl_manager/le_impl.h
@@ -61,11 +61,9 @@
       bool crash_on_unknown_handle)
       : hci_layer_(hci_layer),
         controller_(controller),
+        handler_(handler),
         round_robin_scheduler_(round_robin_scheduler),
         crash_on_unknown_handle_(crash_on_unknown_handle) {
-    hci_layer_ = hci_layer;
-    controller_ = controller;
-    handler_ = handler;
     le_acl_connection_interface_ = hci_layer_->GetLeAclConnectionInterface(
         handler_->BindOn(this, &le_impl::on_le_event),
         handler_->BindOn(this, &le_impl::on_le_disconnect),
diff --git a/system/gd/rust/packets/build.rs b/system/gd/rust/packets/build.rs
index 9bd6d58..0e58cbf 100644
--- a/system/gd/rust/packets/build.rs
+++ b/system/gd/rust/packets/build.rs
@@ -14,7 +14,7 @@
 //  limitations under the License.
 
 use std::env;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 
 fn main() {
@@ -34,8 +34,14 @@
     let outputted = [out_dir.join("../../hci/hci_packets.rs")];
 
     // Find the packetgen tool. Expecting it at CARGO_HOME/bin
-    let packetgen =
-        PathBuf::from(env::var("CARGO_HOME").unwrap()).join("bin").join("bluetooth_packetgen");
+    let packetgen = match env::var("CARGO_HOME") {
+        Ok(dir) => PathBuf::from(dir).join("bin").join("bluetooth_packetgen"),
+        Err(_) => PathBuf::from("bluetooth_packetgen"),
+    };
+
+    if !Path::new(packetgen.as_os_str()).exists() {
+        panic!("Unable to locate bluetooth packet generator:{:?}", packetgen.as_os_str().to_str().unwrap());
+    }
 
     for i in 0..input_files.len() {
         let output = Command::new(packetgen.as_os_str().to_str().unwrap())
diff --git a/system/stack/btm/ble_scanner_hci_interface.cc b/system/stack/btm/ble_scanner_hci_interface.cc
index 26a1924..5d3686b 100644
--- a/system/stack/btm/ble_scanner_hci_interface.cc
+++ b/system/stack/btm/ble_scanner_hci_interface.cc
@@ -211,7 +211,7 @@
 
   void OnPeriodicScanResult(uint16_t sync_handle, uint8_t tx_power, int8_t rssi,
                             uint8_t cte_type, uint8_t pkt_data_status,
-                            uint8_t pkt_data_len, uint8_t* p_pkt_data) {
+                            uint8_t pkt_data_len, const uint8_t* p_pkt_data) {
     // The observer should handle the caching and reassembly of the fragmented
     // packet.
     if (scan_event_observer) {
@@ -351,7 +351,7 @@
 }
 
 void btm_ble_process_periodic_adv_sync_est_evt(uint8_t data_len,
-                                               uint8_t* data) {
+                                               const uint8_t* data) {
   uint16_t sync_handle, adv_interval;
   uint8_t status, adv_sid, adv_addr_type, adv_phy, adv_clock_accuracy;
   RawAddress adv_addr;
@@ -378,8 +378,8 @@
   }
 }
 
-void btm_ble_process_periodic_adv_pkt(uint8_t data_len, uint8_t* data) {
-  uint8_t* p = data;
+void btm_ble_process_periodic_adv_pkt(uint8_t data_len, const uint8_t* data) {
+  const uint8_t* p = data;
   uint16_t sync_handle;
   uint8_t tx_power, cte_type, pkt_data_status, pkt_data_len;
   int8_t rssi;
@@ -394,7 +394,7 @@
   STREAM_TO_UINT8(pkt_data_status, p);
   STREAM_TO_UINT8(pkt_data_len, p);
 
-  uint8_t* pkt_data = p;
+  const uint8_t* pkt_data = p;
   p += pkt_data_len;
 
   if (p > data + data_len) {
diff --git a/system/stack/btm/btm_ble_int.h b/system/stack/btm/btm_ble_int.h
index 8c778f2..7a3b1ef 100644
--- a/system/stack/btm/btm_ble_int.h
+++ b/system/stack/btm/btm_ble_int.h
@@ -34,8 +34,9 @@
 #include "stack/include/hci_error_code.h"
 #include "types/raw_address.h"
 
-extern void btm_ble_process_periodic_adv_sync_est_evt(uint8_t len, uint8_t* p);
-extern void btm_ble_process_periodic_adv_pkt(uint8_t len, uint8_t* p);
+extern void btm_ble_process_periodic_adv_sync_est_evt(uint8_t len,
+                                                      const uint8_t* p);
+extern void btm_ble_process_periodic_adv_pkt(uint8_t len, const uint8_t* p);
 extern void btm_ble_process_periodic_adv_sync_lost_evt(uint8_t len, uint8_t* p);
 extern void btm_send_hci_set_scan_params(uint8_t scan_type, uint16_t scan_int,
                                          uint16_t scan_win,
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index e88d825..6680864 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -435,11 +435,13 @@
           break;
 
         case HCI_BLE_PERIODIC_ADV_SYNC_EST_EVT:
-          btm_ble_process_periodic_adv_sync_est_evt(ble_evt_len, p);
+          btm_ble_process_periodic_adv_sync_est_evt(
+              ble_evt_len, const_cast<const uint8_t*>(p));
           break;
 
         case HCI_BLE_PERIODIC_ADV_REPORT_EVT:
-          btm_ble_process_periodic_adv_pkt(ble_evt_len, p);
+          btm_ble_process_periodic_adv_pkt(ble_evt_len,
+                                           const_cast<const uint8_t*>(p));
           break;
 
         case HCI_BLE_PERIODIC_ADV_SYNC_LOST_EVT:
diff --git a/system/stack/include/ble_hci_link_interface.h b/system/stack/include/ble_hci_link_interface.h
index 553716a..2fe61bb 100644
--- a/system/stack/include/ble_hci_link_interface.h
+++ b/system/stack/include/ble_hci_link_interface.h
@@ -50,6 +50,7 @@
 extern void btm_ble_add_resolving_list_entry_complete(uint8_t* p,
                                                       uint16_t evt_len);
 extern void btm_ble_clear_resolving_list_complete(uint8_t* p, uint16_t evt_len);
-extern void btm_ble_process_periodic_adv_pkt(uint8_t len, uint8_t* p);
-extern void btm_ble_process_periodic_adv_sync_est_evt(uint8_t len, uint8_t* p);
+extern void btm_ble_process_periodic_adv_pkt(uint8_t len, const uint8_t* p);
+extern void btm_ble_process_periodic_adv_sync_est_evt(uint8_t len,
+                                                      const uint8_t* p);
 extern void btm_ble_process_periodic_adv_sync_lost_evt(uint8_t len, uint8_t* p);
diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc
index 9892489..113723e 100644
--- a/system/stack/l2cap/l2c_ble.cc
+++ b/system/stack/l2cap/l2c_ble.cc
@@ -1431,6 +1431,7 @@
 
     if (status != BTM_SUCCESS) {
       (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
+      osi_free(p_buf);
     } else {
       if (sec_act == BTM_SEC_ENCRYPT_MITM) {
         if (BTM_IsLinkKeyAuthed(p_bda, transport))
@@ -1448,24 +1449,28 @@
         (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
                                status);
       }
+      osi_free(p_buf);
     }
   } else {
     L2CAP_TRACE_WARNING(
         "%s Security complete for request not initiated from L2CAP", __func__);
     return;
   }
-  osi_free(p_buf);
 
   while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
     p_buf = (tL2CAP_SEC_DATA*)fixed_queue_dequeue(p_lcb->le_sec_pending_q);
 
-    if (status != BTM_SUCCESS)
+    if (status != BTM_SUCCESS) {
       (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
-    else
+      osi_free(p_buf);
+    }
+    else {
       l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
-                           p_buf->p_callback, p_buf->p_ref_data);
+          p_buf->p_callback, p_buf->p_ref_data);
 
-    osi_free(p_buf);
+      osi_free(p_buf);
+      break;
+    }
   }
 }
 
diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc
index 56c9d83..f480511 100644
--- a/system/stack/l2cap/l2c_link.cc
+++ b/system/stack/l2cap/l2c_link.cc
@@ -833,6 +833,8 @@
 static bool l2c_link_check_power_mode(tL2C_LCB* p_lcb) {
   bool need_to_active = false;
 
+  // Return false as LM modes are applicable for BREDR transport
+  if (p_lcb->is_transport_ble()) return false;
   /*
    * We only switch park to active only if we have unsent packets
    */
@@ -849,7 +851,7 @@
   }
 
   /* if we have packets to send */
-  if (need_to_active && !p_lcb->is_transport_ble()) {
+  if (need_to_active) {
     /* check power mode */
     tBTM_PM_MODE mode;
     if (BTM_ReadPowerMode(p_lcb->remote_bd_addr, &mode)) {
diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc
index e78da80..ebb7a6d 100644
--- a/system/stack/l2cap/l2c_utils.cc
+++ b/system/stack/l2cap/l2c_utils.cc
@@ -1574,6 +1574,9 @@
 
   /* Flag as not in use */
   p_ccb->in_use = false;
+  // Clear Remote CID and Local Id
+  p_ccb->remote_cid = 0;
+  p_ccb->local_id = 0;
 
   /* If no channels on the connection, start idle timeout */
   if ((p_lcb) && p_lcb->in_use) {
diff --git a/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.cc b/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.cc
index 8a69f1f..bbaa954 100644
--- a/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.cc
+++ b/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.cc
@@ -61,12 +61,12 @@
 
 // Mocked functions, if any
 void btm_ble_process_periodic_adv_sync_est_evt(uint8_t data_len,
-                                               uint8_t* data) {
+                                               const uint8_t* data) {
   mock_function_count_map[__func__]++;
   test::mock::stack_btm_ble_scanner_hci_interface::
       btm_ble_process_periodic_adv_sync_est_evt(data_len, data);
 }
-void btm_ble_process_periodic_adv_pkt(uint8_t data_len, uint8_t* data) {
+void btm_ble_process_periodic_adv_pkt(uint8_t data_len, const uint8_t* data) {
   mock_function_count_map[__func__]++;
   test::mock::stack_btm_ble_scanner_hci_interface::
       btm_ble_process_periodic_adv_pkt(data_len, data);
diff --git a/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.h b/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.h
index a28a498..79343e0 100644
--- a/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.h
+++ b/system/test/mock/mock_stack_btm_ble_scanner_hci_interface.h
@@ -49,9 +49,11 @@
 // Params: uint8_t data_len, uint8_t* data
 // Returns: void
 struct btm_ble_process_periodic_adv_sync_est_evt {
-  std::function<void(uint8_t data_len, uint8_t* data)> body{
-      [](uint8_t data_len, uint8_t* data) {}};
-  void operator()(uint8_t data_len, uint8_t* data) { body(data_len, data); };
+  std::function<void(uint8_t data_len, const uint8_t* data)> body{
+      [](uint8_t data_len, const uint8_t* data) {}};
+  void operator()(uint8_t data_len, const uint8_t* data) {
+    body(data_len, data);
+  };
 };
 extern struct btm_ble_process_periodic_adv_sync_est_evt
     btm_ble_process_periodic_adv_sync_est_evt;
@@ -59,9 +61,11 @@
 // Params: uint8_t data_len, uint8_t* data
 // Returns: void
 struct btm_ble_process_periodic_adv_pkt {
-  std::function<void(uint8_t data_len, uint8_t* data)> body{
-      [](uint8_t data_len, uint8_t* data) {}};
-  void operator()(uint8_t data_len, uint8_t* data) { body(data_len, data); };
+  std::function<void(uint8_t data_len, const uint8_t* data)> body{
+      [](uint8_t data_len, const uint8_t* data) {}};
+  void operator()(uint8_t data_len, const uint8_t* data) {
+    body(data_len, data);
+  };
 };
 extern struct btm_ble_process_periodic_adv_pkt btm_ble_process_periodic_adv_pkt;
 // Name: btm_ble_process_periodic_adv_sync_lost_evt
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
index e70a8c8..4613cbe 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
@@ -522,4 +522,13 @@
   return {};
 }
 
+std::vector<uint16_t> AclConnectionHandler::GetAclHandles() const {
+  std::vector<uint16_t> keys;
+
+  for (const auto& pair : acl_connections_) {
+    keys.push_back(pair.first);
+  }
+  return keys;
+}
+
 }  // namespace test_vendor_lib
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
index 0199609..008a293 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
+++ b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
@@ -120,6 +120,8 @@
   StreamParameters GetStreamParameters(uint16_t handle) const;
   GroupParameters GetGroupParameters(uint8_t id) const;
 
+  std::vector<uint16_t> GetAclHandles() const;
+
  private:
   std::unordered_map<uint16_t, AclConnection> acl_connections_;
   std::unordered_map<uint16_t, ScoConnection> sco_connections_;
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
index f54390f..7a56706 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
@@ -61,6 +61,11 @@
   link_layer_controller_.TimerTick();
 }
 
+void DualModeController::Close() {
+  link_layer_controller_.Close();
+  Device::Close();
+}
+
 void DualModeController::SendCommandCompleteUnknownOpCodeEvent(uint16_t command_opcode) const {
   std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
       std::make_unique<bluetooth::packet::RawBuilder>();
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
index 8fa5486..1e88f51 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
+++ b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
@@ -69,6 +69,8 @@
 
   virtual void TimerTick() override;
 
+  virtual void Close() override;
+
   // Route commands and data from the stack.
   void HandleAcl(std::shared_ptr<std::vector<uint8_t>> acl_packet);
   void HandleCommand(std::shared_ptr<std::vector<uint8_t>> command_packet);
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
index f65219d..2374ca0 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -37,7 +37,7 @@
 
 constexpr uint16_t kNumCommandPackets = 0x01;
 
-constexpr milliseconds kNoDelayMs(1);
+constexpr milliseconds kNoDelayMs(0);
 constexpr milliseconds kShortDelayMs(5);
 constexpr milliseconds kLongDelayMs(200);
 
@@ -2051,6 +2051,12 @@
   LeAdvertising();
 }
 
+void LinkLayerController::Close() {
+  for (auto handle : connections_.GetAclHandles()) {
+    Disconnect(handle, static_cast<uint8_t>(ErrorCode::CONNECTION_TIMEOUT));
+  }
+}
+
 void LinkLayerController::LeAdvertising() {
   steady_clock::time_point now = steady_clock::now();
   for (auto& advertiser : advertisers_) {
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
index d2966ed..097e972 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
+++ b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
@@ -102,6 +102,8 @@
 
   void TimerTick();
 
+  void Close();
+
   AsyncTaskId ScheduleTask(std::chrono::milliseconds delay_ms, const TaskCallback& task);
 
   void CancelScheduledTask(AsyncTaskId task);
diff --git a/system/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc b/system/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc
index 296df3e..1a0bcb5 100644
--- a/system/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc
+++ b/system/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc
@@ -137,7 +137,7 @@
   if (socket_) {
     socket_->Close();
   }
-  Device::Close();
+  DualModeController::Close();
 }