From 5fd37a23a2281a8d65b327aa8bb8011478c120aa Mon Sep 17 00:00:00 2001
From: David Duarte <licorne@google.com>
Date: Mon, 15 May 2023 11:31:05 +0000
Subject: [PATCH] Revert "Remove unused dut_mode from bluetooth interface"

This reverts commit 0fd84ef210ae59e959948eccba35fd18386ebb94.

Reason for revert: b/269397845

Bug: 269397845
Test: mma
Change-Id: I0bc217670292449e0eab113688a4555833ca4271
---
 ...oid_bluetooth_btservice_AdapterService.cpp |  5 ++
 system/bta/dm/bta_dm_api.cc                   |  6 ++
 system/bta/include/bta_api.h                  | 12 ++++
 system/btif/include/btif_api.h                | 21 ++++++
 system/btif/src/bluetooth.cc                  | 28 ++++++++
 system/btif/src/btif_core.cc                  | 70 ++++++++++++++++++-
 system/btif/test/btif_core_test.cc            |  2 +
 system/btif/test/btif_hh_test.cc              |  1 +
 system/gd/rust/topshim/src/btif.rs            |  2 +
 system/include/hardware/bluetooth.h           | 15 ++++
 system/main/shim/btm_api.h                    | 17 +++++
 system/stack/btm/btm_devctl.cc                | 44 ++++++++++++
 system/stack/hcic/hcicmds.cc                  | 54 ++++++++++++++
 system/stack/include/btm_api.h                | 17 +++++
 system/stack/include/hcimsgs.h                |  7 ++
 system/test/headless/headless.cc              |  7 ++
 system/test/mock/mock_bta_dm_api.cc           |  5 ++
 system/test/mock/mock_bta_dm_api.h            |  9 +++
 system/test/mock/mock_btif_bluetooth.cc       | 10 +++
 system/test/mock/mock_btif_bluetooth.h        | 19 +++++
 system/test/mock/mock_btif_core.cc            |  8 +++
 system/test/mock/mock_stack_btm_devctl.cc     |  4 ++
 system/test/mock/mock_stack_hcic_hcicmds.cc   | 12 ++++
 system/test/mock/mock_stack_hcic_hcicmds.h    | 24 +++++++
 24 files changed, 398 insertions(+), 1 deletion(-)

diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 7648871be13..32ca755e908 100644
--- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -685,6 +685,10 @@ static void callback_thread_event(bt_cb_thread_evt event) {
   }
 }
 
+static void dut_mode_recv_callback(uint16_t opcode, uint8_t* buf, uint8_t len) {
+
+}
+
 static void energy_info_recv_callback(bt_activity_energy_info* p_energy_info,
                                       bt_uid_traffic_t* uid_data) {
   CallbackEnv sCallbackEnv(__func__);
@@ -728,6 +732,7 @@ static bt_callbacks_t sBluetoothCallbacks = {sizeof(sBluetoothCallbacks),
                                              le_address_associate_callback,
                                              acl_state_changed_callback,
                                              callback_thread_event,
+                                             dut_mode_recv_callback,
                                              energy_info_recv_callback,
                                              link_quality_report_callback,
                                              generate_local_oob_data_callback,
diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc
index 325d82ef75b..e31d66737f9 100644
--- a/system/bta/dm/bta_dm_api.cc
+++ b/system/bta/dm/bta_dm_api.cc
@@ -55,6 +55,12 @@ void BTA_dm_init() {
   BTM_SetConsolidationCallback(bta_dm_consolidate);
 }
 
+/** Enables bluetooth device under test mode */
+void BTA_EnableTestMode(void) {
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(base::IgnoreResult(BTM_EnableTestMode)));
+}
+
 /** This function sets the Bluetooth name of local device */
 void BTA_DmSetDeviceName(const char* p_name) {
   std::vector<uint8_t> name(BD_NAME_LEN + 1);
diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h
index 97a57487316..5b7d14069ea 100644
--- a/system/bta/include/bta_api.h
+++ b/system/bta/include/bta_api.h
@@ -741,6 +741,18 @@ enum {
 
 void BTA_dm_init();
 
+/*******************************************************************************
+ *
+ * Function         BTA_EnableTestMode
+ *
+ * Description      Enables bluetooth device under test mode
+ *
+ *
+ * Returns          tBTA_STATUS
+ *
+ ******************************************************************************/
+extern void BTA_EnableTestMode(void);
+
 /*******************************************************************************
  *
  * Function         BTA_DmSetDeviceName
diff --git a/system/btif/include/btif_api.h b/system/btif/include/btif_api.h
index 55b9da1ac65..6a44658b41d 100644
--- a/system/btif/include/btif_api.h
+++ b/system/btif/include/btif_api.h
@@ -329,6 +329,27 @@ bt_status_t btif_dm_get_adapter_property(bt_property_t* prop);
  ******************************************************************************/
 void btif_dm_get_remote_services(const RawAddress remote_addr, int transport);
 
+/*******************************************************************************
+ *
+ * Function         btif_dut_mode_configure
+ *
+ * Description      Configure Test Mode - 'enable' to 1 puts the device in test
+ *                  mode and 0 exits test mode
+ *
+ ******************************************************************************/
+void btif_dut_mode_configure(uint8_t enable);
+
+bool btif_is_dut_mode();
+
+/*******************************************************************************
+ *
+ * Function         btif_dut_mode_send
+ *
+ * Description     Sends a HCI Vendor specific command to the controller
+ *
+ ******************************************************************************/
+void btif_dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len);
+
 /*******************************************************************************
  *
  * Function         btif_dm_read_energy_info
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index 9d0ef836c23..24c45b3b7fb 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -917,6 +917,32 @@ static const void* get_profile_interface(const char* profile_id) {
   return NULL;
 }
 
+int dut_mode_configure(uint8_t enable) {
+  if (!interface_ready()) return BT_STATUS_NOT_READY;
+  if (!stack_manager_get_interface()->get_stack_is_running())
+    return BT_STATUS_NOT_READY;
+
+  do_in_main_thread(FROM_HERE, base::BindOnce(btif_dut_mode_configure, enable));
+  return BT_STATUS_SUCCESS;
+}
+
+int dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len) {
+  if (!interface_ready()) return BT_STATUS_NOT_READY;
+  if (!btif_is_dut_mode()) return BT_STATUS_FAIL;
+
+  uint8_t* copy = (uint8_t*)osi_calloc(len);
+  memcpy(copy, buf, len);
+
+  do_in_main_thread(FROM_HERE,
+                    base::BindOnce(
+                        [](uint16_t opcode, uint8_t* buf, uint8_t len) {
+                          btif_dut_mode_send(opcode, buf, len);
+                          osi_free(buf);
+                        },
+                        opcode, copy, len));
+  return BT_STATUS_SUCCESS;
+}
+
 static bt_os_callouts_t* wakelock_os_callouts_saved = nullptr;
 
 static int acquire_wake_lock_cb(const char* lock_name) {
@@ -1108,6 +1134,8 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
     .pin_reply = pin_reply,
     .ssp_reply = ssp_reply,
     .get_profile_interface = get_profile_interface,
+    .dut_mode_configure = dut_mode_configure,
+    .dut_mode_send = dut_mode_send,
     .set_os_callouts = set_os_callouts,
     .read_energy_info = read_energy_info,
     .dump = dump,
diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc
index c0499108803..ab609b30756 100644
--- a/system/btif/src/btif_core.cc
+++ b/system/btif/src/btif_core.cc
@@ -94,6 +94,14 @@ static void bt_jni_msg_ready(void* context);
 
 static tBTA_SERVICE_MASK btif_enabled_services = 0;
 
+/*
+ * This variable should be set to 1, if the Bluedroid+BTIF libraries are to
+ * function in DUT mode.
+ *
+ * To set this, the btif_init_bluetooth needs to be called with argument as 1
+ */
+static uint8_t btif_dut_mode = 0;
+
 static MessageLoopThread jni_thread("bt_jni_thread");
 static base::AtExitManager* exit_manager;
 static uid_set_t* uid_set;
@@ -181,6 +189,18 @@ void post_on_bt_jni(BtJniClosure closure) {
          BT_STATUS_SUCCESS);
 }
 
+/*******************************************************************************
+ *
+ * Function         btif_is_dut_mode
+ *
+ * Description      checks if BTIF is currently in DUT mode
+ *
+ * Returns          true if test mode, otherwise false
+ *
+ ******************************************************************************/
+
+bool btif_is_dut_mode() { return btif_dut_mode == 1; }
+
 /*******************************************************************************
  *
  * Function         btif_is_enabled
@@ -192,7 +212,8 @@ void post_on_bt_jni(BtJniClosure closure) {
  ******************************************************************************/
 
 int btif_is_enabled(void) {
-  return (stack_manager_get_interface()->get_stack_is_running());
+  return ((!btif_is_dut_mode()) &&
+          (stack_manager_get_interface()->get_stack_is_running()));
 }
 
 void btif_init_ok() {
@@ -313,10 +334,57 @@ bt_status_t btif_cleanup_bluetooth() {
   jni_thread.ShutDown();
   delete exit_manager;
   exit_manager = nullptr;
+  btif_dut_mode = 0;
   LOG_INFO("%s finished", __func__);
   return BT_STATUS_SUCCESS;
 }
 
+/*******************************************************************************
+ *
+ * Function         btif_dut_mode_cback
+ *
+ * Description     Callback invoked on completion of vendor specific test mode
+ *                 command
+ *
+ * Returns          None
+ *
+ ******************************************************************************/
+static void btif_dut_mode_cback(UNUSED_ATTR tBTM_VSC_CMPL* p) {
+  /* For now nothing to be done. */
+}
+
+/*******************************************************************************
+ *
+ * Function         btif_dut_mode_configure
+ *
+ * Description      Configure Test Mode - 'enable' to 1 puts the device in test
+ *                       mode and 0 exits test mode
+ *
+ ******************************************************************************/
+void btif_dut_mode_configure(uint8_t enable) {
+  BTIF_TRACE_DEBUG("%s", __func__);
+
+  btif_dut_mode = enable;
+  if (enable == 1) {
+    BTA_EnableTestMode();
+  } else {
+    // Can't do in process reset anyways - just quit
+    kill(getpid(), SIGKILL);
+  }
+}
+
+/*******************************************************************************
+ *
+ * Function         btif_dut_mode_send
+ *
+ * Description     Sends a HCI Vendor specific command to the controller
+ *
+ ******************************************************************************/
+void btif_dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len) {
+  BTIF_TRACE_DEBUG("%s", __func__);
+  BTM_VendorSpecificCommand(opcode, len, buf, btif_dut_mode_cback);
+}
+
 /*****************************************************************************
  *
  *   btif api adapter property functions
diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc
index 27df5e1b697..ab37b95cd36 100644
--- a/system/btif/test/btif_core_test.cc
+++ b/system/btif/test/btif_core_test.cc
@@ -85,6 +85,7 @@ void link_quality_report_callback(uint64_t timestamp, int report_id, int rssi,
                                   int packets_not_receive_count,
                                   int negative_acknowledgement_count) {}
 void callback_thread_event(bt_cb_thread_evt evt) { TESTCB; }
+void dut_mode_recv_callback(uint16_t opcode, uint8_t* buf, uint8_t len) {}
 void energy_info_callback(bt_activity_energy_info* energy_info,
                           bt_uid_traffic_t* uid_data) {}
 void generate_local_oob_data_callback(tBT_TRANSPORT transport,
@@ -107,6 +108,7 @@ bt_callbacks_t callbacks = {
     .le_address_associate_cb = le_address_associate_callback,
     .acl_state_changed_cb = acl_state_changed_callback,
     .thread_evt_cb = callback_thread_event,
+    .dut_mode_recv_cb = dut_mode_recv_callback,
     .energy_info_cb = energy_info_callback,
     .link_quality_report_cb = link_quality_report_callback,
     .generate_local_oob_data_cb = generate_local_oob_data_callback,
diff --git a/system/btif/test/btif_hh_test.cc b/system/btif/test/btif_hh_test.cc
index b5efa5c40b7..de215c2689e 100644
--- a/system/btif/test/btif_hh_test.cc
+++ b/system/btif/test/btif_hh_test.cc
@@ -133,6 +133,7 @@ bt_callbacks_t bt_callbacks = {
     .le_address_associate_cb = nullptr,     // le_address_associate_callback
     .acl_state_changed_cb = nullptr,        // acl_state_changed_callback
     .thread_evt_cb = nullptr,               // callback_thread_event
+    .dut_mode_recv_cb = nullptr,            // dut_mode_recv_callback
     .energy_info_cb = nullptr,              // energy_info_callback
     .link_quality_report_cb = nullptr,      // link_quality_report_callback
     .generate_local_oob_data_cb = nullptr,  // generate_local_oob_data_callback
diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs
index 02e5559056f..0973d8ad718 100644
--- a/system/gd/rust/topshim/src/btif.rs
+++ b/system/gd/rust/topshim/src/btif.rs
@@ -884,6 +884,7 @@ pub enum BaseCallbacks {
     ),
     // Unimplemented so far:
     // thread_evt_cb
+    // dut_mode_recv_cb
     // energy_info_cb
     // link_quality_report_cb
     // switch_buffer_size_cb
@@ -1070,6 +1071,7 @@ impl BluetoothInterface {
             le_address_associate_cb: Some(le_address_associate_cb),
             acl_state_changed_cb: Some(acl_state_cb),
             thread_evt_cb: None,
+            dut_mode_recv_cb: None,
             energy_info_cb: None,
             link_quality_report_cb: None,
             generate_local_oob_data_cb: Some(generate_local_oob_data_cb),
diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h
index a44a75d191a..031ce226de8 100644
--- a/system/include/hardware/bluetooth.h
+++ b/system/include/hardware/bluetooth.h
@@ -544,6 +544,12 @@ typedef enum { ASSOCIATE_JVM, DISASSOCIATE_JVM } bt_cb_thread_evt;
  * attach/detach to/from the JVM */
 typedef void (*callback_thread_event)(bt_cb_thread_evt evt);
 
+/** Bluetooth Test Mode Callback */
+/* Receive any HCI event from controller. Must be in DUT Mode for this callback
+ * to be received */
+typedef void (*dut_mode_recv_callback)(uint16_t opcode, uint8_t* buf,
+                                       uint8_t len);
+
 /** Callback invoked when energy details are obtained */
 /* Ctrl_state-Current controller state-Active-1,scan-2,or idle-3 state as
  * defined by HCI spec. If the ctrl_state value is 0, it means the API call
@@ -578,6 +584,7 @@ typedef struct {
   le_address_associate_callback le_address_associate_cb;
   acl_state_changed_callback acl_state_changed_cb;
   callback_thread_event thread_evt_cb;
+  dut_mode_recv_callback dut_mode_recv_cb;
   energy_info_callback energy_info_cb;
   link_quality_report_callback link_quality_report_cb;
   generate_local_oob_data_callback generate_local_oob_data_cb;
@@ -730,6 +737,14 @@ typedef struct {
   /** Get Bluetooth profile interface */
   const void* (*get_profile_interface)(const char* profile_id);
 
+  /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */
+  /* Configure DUT Mode - Use this mode to enter/exit DUT mode */
+  int (*dut_mode_configure)(uint8_t enable);
+
+  /* Send any test HCI (vendor-specific) command to the controller. Must be in
+   * DUT Mode */
+  int (*dut_mode_send)(uint16_t opcode, uint8_t* buf, uint8_t len);
+
   /** Sets the OS call-out functions that bluedroid needs for alarms and wake
    * locks. This should be called immediately after a successful |init|.
    */
diff --git a/system/main/shim/btm_api.h b/system/main/shim/btm_api.h
index 948da468c80..e14eb4a210d 100644
--- a/system/main/shim/btm_api.h
+++ b/system/main/shim/btm_api.h
@@ -921,6 +921,23 @@ void BTM_WritePageTimeout(uint16_t timeout);
  ******************************************************************************/
 void BTM_WriteVoiceSettings(uint16_t settings);
 
+/*******************************************************************************
+ *
+ * Function         BTM_EnableTestMode
+ *
+ * Description      Send HCI the enable device under test command.
+ *
+ *                  Note: Controller can only be taken out of this mode by
+ *                      resetting the controller.
+ *
+ * Returns
+ *      BTM_SUCCESS         Command sent.
+ *      BTM_NO_RESOURCES    If out of resources to send the command.
+ *
+ *
+ ******************************************************************************/
+tBTM_STATUS BTM_EnableTestMode(void);
+
 /*******************************************************************************
  *
  * Function         BTM_ReadRemoteVersion
diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc
index 91cc7b6b817..e3d214793f4 100644
--- a/system/stack/btm/btm_devctl.cc
+++ b/system/stack/btm/btm_devctl.cc
@@ -629,6 +629,50 @@ void BTM_WriteVoiceSettings(uint16_t settings) {
   btsnd_hcic_write_voice_settings((uint16_t)(settings & 0x03ff));
 }
 
+/*******************************************************************************
+ *
+ * Function         BTM_EnableTestMode
+ *
+ * Description      Send HCI the enable device under test command.
+ *
+ *                  Note: Controller can only be taken out of this mode by
+ *                      resetting the controller.
+ *
+ * Returns
+ *      BTM_SUCCESS         Command sent.
+ *      BTM_NO_RESOURCES    If out of resources to send the command.
+ *
+ *
+ ******************************************************************************/
+tBTM_STATUS BTM_EnableTestMode(void) {
+  uint8_t cond;
+
+  BTM_TRACE_EVENT("BTM: BTM_EnableTestMode");
+
+  /* set auto accept connection as this is needed during test mode */
+  /* Allocate a buffer to hold HCI command */
+  cond = HCI_DO_AUTO_ACCEPT_CONNECT;
+  btsnd_hcic_set_event_filter(HCI_FILTER_CONNECTION_SETUP,
+                              HCI_FILTER_COND_NEW_DEVICE, &cond, sizeof(cond));
+
+  /* put device to connectable mode */
+  if (BTM_SetConnectability(BTM_CONNECTABLE) != BTM_SUCCESS) {
+    return BTM_NO_RESOURCES;
+  }
+
+  /* put device to discoverable mode */
+  if (BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE) != BTM_SUCCESS) {
+    return BTM_NO_RESOURCES;
+  }
+
+  /* mask off all of event from controller */
+  bluetooth::shim::BTM_ClearEventMask();
+
+  /* Send the HCI command */
+  btsnd_hcic_enable_test_mode();
+  return (BTM_SUCCESS);
+}
+
 /*******************************************************************************
  *
  * Function         BTM_DeleteStoredLinkKey
diff --git a/system/stack/hcic/hcicmds.cc b/system/stack/hcic/hcicmds.cc
index c49cd713ba2..aa45842da58 100644
--- a/system/stack/hcic/hcicmds.cc
+++ b/system/stack/hcic/hcicmds.cc
@@ -997,6 +997,47 @@ void btsnd_hcic_write_def_policy_set(uint16_t settings) {
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
+void btsnd_hcic_set_event_filter(uint8_t filt_type, uint8_t filt_cond_type,
+                                 uint8_t* filt_cond, uint8_t filt_cond_len) {
+  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
+  uint8_t* pp = (uint8_t*)(p + 1);
+
+  p->offset = 0;
+
+  UINT16_TO_STREAM(pp, HCI_SET_EVENT_FILTER);
+
+  if (filt_type) {
+    p->len = (uint16_t)(HCIC_PREAMBLE_SIZE + 2 + filt_cond_len);
+    UINT8_TO_STREAM(pp, (uint8_t)(2 + filt_cond_len));
+
+    UINT8_TO_STREAM(pp, filt_type);
+    UINT8_TO_STREAM(pp, filt_cond_type);
+
+    if (filt_cond_type == HCI_FILTER_COND_DEVICE_CLASS) {
+      DEVCLASS_TO_STREAM(pp, filt_cond);
+      filt_cond += DEV_CLASS_LEN;
+      DEVCLASS_TO_STREAM(pp, filt_cond);
+      filt_cond += DEV_CLASS_LEN;
+
+      filt_cond_len -= (2 * DEV_CLASS_LEN);
+    } else if (filt_cond_type == HCI_FILTER_COND_BD_ADDR) {
+      BDADDR_TO_STREAM(pp, *((RawAddress*)filt_cond));
+      filt_cond += BD_ADDR_LEN;
+
+      filt_cond_len -= BD_ADDR_LEN;
+    }
+
+    if (filt_cond_len) ARRAY_TO_STREAM(pp, filt_cond, filt_cond_len);
+  } else {
+    p->len = (uint16_t)(HCIC_PREAMBLE_SIZE + 1);
+    UINT8_TO_STREAM(pp, 1);
+
+    UINT8_TO_STREAM(pp, filt_type);
+  }
+
+  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+}
+
 void btsnd_hcic_write_pin_type(uint8_t type) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
@@ -1581,6 +1622,19 @@ void btsnd_hcic_read_failed_contact_counter(uint16_t handle) {
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
+void btsnd_hcic_enable_test_mode(void) {
+  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
+  uint8_t* pp = (uint8_t*)(p + 1);
+
+  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+  p->offset = 0;
+
+  UINT16_TO_STREAM(pp, HCI_ENABLE_DEV_UNDER_TEST_MODE);
+  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_CMD);
+
+  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+}
+
 void btsnd_hcic_write_inqscan_type(uint8_t type) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
diff --git a/system/stack/include/btm_api.h b/system/stack/include/btm_api.h
index 72f680d8553..12fb5b194ba 100644
--- a/system/stack/include/btm_api.h
+++ b/system/stack/include/btm_api.h
@@ -220,6 +220,23 @@ void BTM_WritePageTimeout(uint16_t timeout);
  ******************************************************************************/
 void BTM_WriteVoiceSettings(uint16_t settings);
 
+/*******************************************************************************
+ *
+ * Function         BTM_EnableTestMode
+ *
+ * Description      Send HCI the enable device under test command.
+ *
+ *                  Note: Controller can only be taken out of this mode by
+ *                      resetting the controller.
+ *
+ * Returns
+ *      BTM_SUCCESS         Command sent.
+ *      BTM_NO_RESOURCES    If out of resources to send the command.
+ *
+ *
+ ******************************************************************************/
+tBTM_STATUS BTM_EnableTestMode(void);
+
 /*******************************************************************************
  * DEVICE DISCOVERY FUNCTIONS - Inquiry, Remote Name, Discovery, Class of Device
  ******************************************************************************/
diff --git a/system/stack/include/hcimsgs.h b/system/stack/include/hcimsgs.h
index ac9deb17e62..675c64e6978 100644
--- a/system/stack/include/hcimsgs.h
+++ b/system/stack/include/hcimsgs.h
@@ -203,6 +203,12 @@ void btsnd_hcic_enhanced_flush(uint16_t handle, uint8_t packet_type);
 
 /**** end of Simple Pairing Commands ****/
 
+extern void btsnd_hcic_set_event_filter(uint8_t filt_type,
+                                        uint8_t filt_cond_type,
+                                        uint8_t* filt_cond,
+                                        uint8_t filt_cond_len);
+/* Set Event Filter */
+
 /* Delete Stored Key */
 void btsnd_hcic_delete_stored_key(const RawAddress& bd_addr,
                                   bool delete_all_flag);
@@ -253,6 +259,7 @@ void btsnd_hcic_read_rssi(uint16_t handle); /* Read RSSI */
 using ReadEncKeySizeCb = base::OnceCallback<void(uint8_t, uint16_t, uint8_t)>;
 void btsnd_hcic_read_encryption_key_size(uint16_t handle, ReadEncKeySizeCb cb);
 void btsnd_hcic_read_failed_contact_counter(uint16_t handle);
+void btsnd_hcic_enable_test_mode(void); /* Enable Device Under Test Mode */
 void btsnd_hcic_write_pagescan_type(uint8_t type); /* Write Page Scan Type */
 void btsnd_hcic_write_inqscan_type(uint8_t type);  /* Write Inquiry Scan Type */
 void btsnd_hcic_write_inquiry_mode(uint8_t type);  /* Write Inquiry Mode */
diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc
index f2cc739beb6..551a6d666a0 100644
--- a/system/test/headless/headless.cc
+++ b/system/test/headless/headless.cc
@@ -199,6 +199,12 @@ void thread_event([[maybe_unused]] bt_cb_thread_evt evt) {
   LOG_INFO("%s", __func__);
 }
 
+void dut_mode_recv([[maybe_unused]] uint16_t opcode,
+                   [[maybe_unused]] uint8_t* buf,
+                   [[maybe_unused]] uint8_t len) {
+  LOG_INFO("%s", __func__);
+}
+
 void energy_info([[maybe_unused]] bt_activity_energy_info* energy_info,
                  [[maybe_unused]] bt_uid_traffic_t* uid_data) {
   LOG_INFO("%s", __func__);
@@ -219,6 +225,7 @@ bt_callbacks_t bt_callbacks{
     .le_address_associate_cb = le_address_associate,
     .acl_state_changed_cb = acl_state_changed,
     .thread_evt_cb = thread_event,
+    .dut_mode_recv_cb = dut_mode_recv,
     .energy_info_cb = energy_info,
     .link_quality_report_cb = link_quality_report,
     .switch_buffer_size_cb = switch_buffer_size,
diff --git a/system/test/mock/mock_bta_dm_api.cc b/system/test/mock/mock_bta_dm_api.cc
index c61070b7159..1d9042f61e9 100644
--- a/system/test/mock/mock_bta_dm_api.cc
+++ b/system/test/mock/mock_bta_dm_api.cc
@@ -67,6 +67,7 @@ struct BTA_DmSetBlePrefConnParams BTA_DmSetBlePrefConnParams;
 struct BTA_DmSetDeviceName BTA_DmSetDeviceName;
 struct BTA_DmSetEncryption BTA_DmSetEncryption;
 struct BTA_DmSetLocalDiRecord BTA_DmSetLocalDiRecord;
+struct BTA_EnableTestMode BTA_EnableTestMode;
 struct BTA_GetEirService BTA_GetEirService;
 struct BTA_VendorInit BTA_VendorInit;
 struct BTA_dm_init BTA_dm_init;
@@ -215,6 +216,10 @@ tBTA_STATUS BTA_DmSetLocalDiRecord(tSDP_DI_RECORD* p_device_info,
   return test::mock::bta_dm_api::BTA_DmSetLocalDiRecord(p_device_info,
                                                         p_handle);
 }
+void BTA_EnableTestMode(void) {
+  inc_func_call_count(__func__);
+  test::mock::bta_dm_api::BTA_EnableTestMode();
+}
 void BTA_GetEirService(const uint8_t* p_eir, size_t eir_len,
                        tBTA_SERVICE_MASK* p_services) {
   inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_bta_dm_api.h b/system/test/mock/mock_bta_dm_api.h
index cd3473ee745..78ca8145cfd 100644
--- a/system/test/mock/mock_bta_dm_api.h
+++ b/system/test/mock/mock_bta_dm_api.h
@@ -418,6 +418,15 @@ struct BTA_DmSetLocalDiRecord {
 };
 extern struct BTA_DmSetLocalDiRecord BTA_DmSetLocalDiRecord;
 
+// Name: BTA_EnableTestMode
+// Params: void
+// Return: void
+struct BTA_EnableTestMode {
+  std::function<void(void)> body{[](void) {}};
+  void operator()(void) { body(); };
+};
+extern struct BTA_EnableTestMode BTA_EnableTestMode;
+
 // Name: BTA_GetEirService
 // Params: uint8_t* p_eir, size_t eir_len, tBTA_SERVICE_MASK* p_services
 // Return: void
diff --git a/system/test/mock/mock_btif_bluetooth.cc b/system/test/mock/mock_btif_bluetooth.cc
index e9a6a8188ee..a5994721ea9 100644
--- a/system/test/mock/mock_btif_bluetooth.cc
+++ b/system/test/mock/mock_btif_bluetooth.cc
@@ -45,6 +45,8 @@ namespace btif_bluetooth {
 struct is_atv_device is_atv_device;
 struct is_common_criteria_mode is_common_criteria_mode;
 struct is_restricted_mode is_restricted_mode;
+struct dut_mode_configure dut_mode_configure;
+struct dut_mode_send dut_mode_send;
 struct get_common_criteria_config_compare_result
     get_common_criteria_config_compare_result;
 struct get_remote_device_properties get_remote_device_properties;
@@ -70,6 +72,14 @@ bool is_restricted_mode() {
   inc_func_call_count(__func__);
   return test::mock::btif_bluetooth::is_restricted_mode();
 }
+int dut_mode_configure(uint8_t enable) {
+  inc_func_call_count(__func__);
+  return test::mock::btif_bluetooth::dut_mode_configure(enable);
+}
+int dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len) {
+  inc_func_call_count(__func__);
+  return test::mock::btif_bluetooth::dut_mode_send(opcode, buf, len);
+}
 int get_common_criteria_config_compare_result() {
   inc_func_call_count(__func__);
   return test::mock::btif_bluetooth::
diff --git a/system/test/mock/mock_btif_bluetooth.h b/system/test/mock/mock_btif_bluetooth.h
index a272a4ffa5d..c007631f733 100644
--- a/system/test/mock/mock_btif_bluetooth.h
+++ b/system/test/mock/mock_btif_bluetooth.h
@@ -71,6 +71,25 @@ struct is_restricted_mode {
   bool operator()() { return body(); };
 };
 extern struct is_restricted_mode is_restricted_mode;
+// Name: dut_mode_configure
+// Params: uint8_t enable
+// Returns: int
+struct dut_mode_configure {
+  std::function<int(uint8_t enable)> body{[](uint8_t enable) { return 0; }};
+  int operator()(uint8_t enable) { return body(enable); };
+};
+extern struct dut_mode_configure dut_mode_configure;
+// Name: dut_mode_send
+// Params: uint16_t opcode, uint8_t* buf, uint8_t len
+// Returns: int
+struct dut_mode_send {
+  std::function<int(uint16_t opcode, uint8_t* buf, uint8_t len)> body{
+      [](uint16_t opcode, uint8_t* buf, uint8_t len) { return 0; }};
+  int operator()(uint16_t opcode, uint8_t* buf, uint8_t len) {
+    return body(opcode, buf, len);
+  };
+};
+extern struct dut_mode_send dut_mode_send;
 // Name: get_common_criteria_config_compare_result
 // Params:
 // Returns: int
diff --git a/system/test/mock/mock_btif_core.cc b/system/test/mock/mock_btif_core.cc
index 75544b45f04..59de7df0185 100644
--- a/system/test/mock/mock_btif_core.cc
+++ b/system/test/mock/mock_btif_core.cc
@@ -35,6 +35,10 @@
 #define UNUSED_ATTR
 #endif
 
+bool btif_is_dut_mode() {
+  inc_func_call_count(__func__);
+  return false;
+}
 bool is_on_jni_thread() {
   inc_func_call_count(__func__);
   return false;
@@ -94,6 +98,10 @@ void btif_adapter_properties_evt(bt_status_t status, uint32_t num_props,
 void btif_disable_service(tBTA_SERVICE_ID service_id) {
   inc_func_call_count(__func__);
 }
+void btif_dut_mode_configure(uint8_t enable) { inc_func_call_count(__func__); }
+void btif_dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len) {
+  inc_func_call_count(__func__);
+}
 void btif_enable_bluetooth_evt() { inc_func_call_count(__func__); }
 void btif_enable_service(tBTA_SERVICE_ID service_id) {
   inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_stack_btm_devctl.cc b/system/test/mock/mock_stack_btm_devctl.cc
index 48959cd9eaa..b24df121410 100644
--- a/system/test/mock/mock_stack_btm_devctl.cc
+++ b/system/test/mock/mock_stack_btm_devctl.cc
@@ -75,6 +75,10 @@ tBTM_STATUS BTM_DeleteStoredLinkKey(const RawAddress* bd_addr,
   inc_func_call_count(__func__);
   return BTM_SUCCESS;
 }
+tBTM_STATUS BTM_EnableTestMode(void) {
+  inc_func_call_count(__func__);
+  return BTM_SUCCESS;
+}
 tBTM_STATUS BTM_ReadLocalDeviceName(const char** p_name) {
   inc_func_call_count(__func__);
   return BTM_SUCCESS;
diff --git a/system/test/mock/mock_stack_hcic_hcicmds.cc b/system/test/mock/mock_stack_hcic_hcicmds.cc
index 9d2af01caa0..242e6146939 100644
--- a/system/test/mock/mock_stack_hcic_hcicmds.cc
+++ b/system/test/mock/mock_stack_hcic_hcicmds.cc
@@ -44,6 +44,7 @@ struct btsnd_hcic_change_conn_type btsnd_hcic_change_conn_type;
 struct btsnd_hcic_change_name btsnd_hcic_change_name;
 struct btsnd_hcic_create_conn_cancel btsnd_hcic_create_conn_cancel;
 struct btsnd_hcic_delete_stored_key btsnd_hcic_delete_stored_key;
+struct btsnd_hcic_enable_test_mode btsnd_hcic_enable_test_mode;
 struct btsnd_hcic_enhanced_accept_synchronous_connection
     btsnd_hcic_enhanced_accept_synchronous_connection;
 struct btsnd_hcic_enhanced_flush btsnd_hcic_enhanced_flush;
@@ -76,6 +77,7 @@ struct btsnd_hcic_rmt_name_req btsnd_hcic_rmt_name_req;
 struct btsnd_hcic_rmt_name_req_cancel btsnd_hcic_rmt_name_req_cancel;
 struct btsnd_hcic_rmt_ver_req btsnd_hcic_rmt_ver_req;
 struct btsnd_hcic_set_conn_encrypt btsnd_hcic_set_conn_encrypt;
+struct btsnd_hcic_set_event_filter btsnd_hcic_set_event_filter;
 struct btsnd_hcic_setup_esco_conn btsnd_hcic_setup_esco_conn;
 struct btsnd_hcic_sniff_mode btsnd_hcic_sniff_mode;
 struct btsnd_hcic_sniff_sub_rate btsnd_hcic_sniff_sub_rate;
@@ -150,6 +152,10 @@ void btsnd_hcic_delete_stored_key(const RawAddress& bd_addr,
   test::mock::stack_hcic_hcicmds::btsnd_hcic_delete_stored_key(bd_addr,
                                                                delete_all_flag);
 }
+void btsnd_hcic_enable_test_mode(void) {
+  inc_func_call_count(__func__);
+  test::mock::stack_hcic_hcicmds::btsnd_hcic_enable_test_mode();
+}
 void btsnd_hcic_enhanced_accept_synchronous_connection(
     const RawAddress& bd_addr, enh_esco_params_t* p_params) {
   inc_func_call_count(__func__);
@@ -289,6 +295,12 @@ void btsnd_hcic_set_conn_encrypt(uint16_t handle, bool enable) {
   inc_func_call_count(__func__);
   test::mock::stack_hcic_hcicmds::btsnd_hcic_set_conn_encrypt(handle, enable);
 }
+void btsnd_hcic_set_event_filter(uint8_t filt_type, uint8_t filt_cond_type,
+                                 uint8_t* filt_cond, uint8_t filt_cond_len) {
+  inc_func_call_count(__func__);
+  test::mock::stack_hcic_hcicmds::btsnd_hcic_set_event_filter(
+      filt_type, filt_cond_type, filt_cond, filt_cond_len);
+}
 void btsnd_hcic_setup_esco_conn(uint16_t handle, uint32_t transmit_bandwidth,
                                 uint32_t receive_bandwidth,
                                 uint16_t max_latency, uint16_t voice,
diff --git a/system/test/mock/mock_stack_hcic_hcicmds.h b/system/test/mock/mock_stack_hcic_hcicmds.h
index 81bbfeba3dd..54a20f03f56 100644
--- a/system/test/mock/mock_stack_hcic_hcicmds.h
+++ b/system/test/mock/mock_stack_hcic_hcicmds.h
@@ -153,6 +153,15 @@ struct btsnd_hcic_delete_stored_key {
 };
 extern struct btsnd_hcic_delete_stored_key btsnd_hcic_delete_stored_key;
 
+// Name: btsnd_hcic_enable_test_mode
+// Params: void
+// Return: void
+struct btsnd_hcic_enable_test_mode {
+  std::function<void(void)> body{[](void) {}};
+  void operator()(void) { body(); };
+};
+extern struct btsnd_hcic_enable_test_mode btsnd_hcic_enable_test_mode;
+
 // Name: btsnd_hcic_enhanced_accept_synchronous_connection
 // Params: const RawAddress& bd_addr, enh_esco_params_t* p_params
 // Return: void
@@ -487,6 +496,21 @@ struct btsnd_hcic_set_conn_encrypt {
 };
 extern struct btsnd_hcic_set_conn_encrypt btsnd_hcic_set_conn_encrypt;
 
+// Name: btsnd_hcic_set_event_filter
+// Params: uint8_t filt_type, uint8_t filt_cond_type, uint8_t* filt_cond,
+// uint8_t filt_cond_len Return: void
+struct btsnd_hcic_set_event_filter {
+  std::function<void(uint8_t filt_type, uint8_t filt_cond_type,
+                     uint8_t* filt_cond, uint8_t filt_cond_len)>
+      body{[](uint8_t filt_type, uint8_t filt_cond_type, uint8_t* filt_cond,
+              uint8_t filt_cond_len) {}};
+  void operator()(uint8_t filt_type, uint8_t filt_cond_type, uint8_t* filt_cond,
+                  uint8_t filt_cond_len) {
+    body(filt_type, filt_cond_type, filt_cond, filt_cond_len);
+  };
+};
+extern struct btsnd_hcic_set_event_filter btsnd_hcic_set_event_filter;
+
 // Name: btsnd_hcic_setup_esco_conn
 // Params: uint16_t handle, uint32_t transmit_bandwidth, uint32_t
 // receive_bandwidth, uint16_t max_latency, uint16_t voice, uint8_t
-- 
GitLab