Revert "Remove unused le_test_mode from bluetooth interface"

This reverts commit 78edce9b0f72a6db4eb41bebf37c42156643ac86.

Reason for revert: b/269397845

Bug: 269397845
Test: mma
Change-Id: I07b66a087d22d6952caa4d54f08cdff028674e9d
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 32ca755..c4b3e7e 100644
--- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -689,6 +689,11 @@
 
 }
 
+static void le_test_mode_recv_callback(bt_status_t status,
+                                       uint16_t packet_count) {
+  ALOGV("%s: status:%d packet_count:%d ", __func__, status, packet_count);
+}
+
 static void energy_info_recv_callback(bt_activity_energy_info* p_energy_info,
                                       bt_uid_traffic_t* uid_data) {
   CallbackEnv sCallbackEnv(__func__);
@@ -733,6 +738,7 @@
                                              acl_state_changed_callback,
                                              callback_thread_event,
                                              dut_mode_recv_callback,
+                                             le_test_mode_recv_callback,
                                              energy_info_recv_callback,
                                              link_quality_report_callback,
                                              generate_local_oob_data_callback,
diff --git a/system/btif/include/btif_api.h b/system/btif/include/btif_api.h
index 6a44658..fbf61cd 100644
--- a/system/btif/include/btif_api.h
+++ b/system/btif/include/btif_api.h
@@ -350,6 +350,12 @@
  ******************************************************************************/
 void btif_dut_mode_send(uint16_t opcode, uint8_t* buf, uint8_t len);
 
+void btif_ble_transmitter_test(uint8_t tx_freq, uint8_t test_data_len,
+                               uint8_t packet_payload);
+
+void btif_ble_receiver_test(uint8_t rx_freq);
+void btif_ble_test_end();
+
 /*******************************************************************************
  *
  * Function         btif_dm_read_energy_info
diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h
index 32488b7..4868e7e 100644
--- a/system/btif/include/btif_common.h
+++ b/system/btif/include/btif_common.h
@@ -228,6 +228,7 @@
                                  bt_conn_direction_t direction,
                                  uint16_t acl_handle);
 void invoke_thread_evt_cb(bt_cb_thread_evt event);
+void invoke_le_test_mode_cb(bt_status_t status, uint16_t count);
 void invoke_energy_info_cb(bt_activity_energy_info energy_info,
                            bt_uid_traffic_t* uid_data);
 void invoke_link_quality_report_cb(
diff --git a/system/btif/include/core_callbacks.h b/system/btif/include/core_callbacks.h
index 79b4218..a10198b 100644
--- a/system/btif/include/core_callbacks.h
+++ b/system/btif/include/core_callbacks.h
@@ -58,6 +58,7 @@
                                       bt_conn_direction_t direction,
                                       uint16_t acl_handle);
   void (*invoke_thread_evt_cb)(bt_cb_thread_evt event);
+  void (*invoke_le_test_mode_cb)(bt_status_t status, uint16_t count);
   void (*invoke_energy_info_cb)(bt_activity_energy_info energy_info,
                                 bt_uid_traffic_t* uid_data);
   void (*invoke_link_quality_report_cb)(uint64_t timestamp, int report_id,
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index 24c45b3..bc854e0 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -325,6 +325,7 @@
       .invoke_le_address_associate_cb = invoke_le_address_associate_cb,
       .invoke_acl_state_changed_cb = invoke_acl_state_changed_cb,
       .invoke_thread_evt_cb = invoke_thread_evt_cb,
+      .invoke_le_test_mode_cb = invoke_le_test_mode_cb,
       .invoke_energy_info_cb = invoke_energy_info_cb,
       .invoke_link_quality_report_cb = invoke_link_quality_report_cb};
   static auto configInterface = ConfigInterfaceImpl();
@@ -943,6 +944,29 @@
   return BT_STATUS_SUCCESS;
 }
 
+int le_test_mode(uint16_t opcode, uint8_t* buf, uint8_t len) {
+  if (!interface_ready()) return BT_STATUS_NOT_READY;
+
+  switch (opcode) {
+    case HCI_BLE_TRANSMITTER_TEST:
+      if (len != 3) return BT_STATUS_PARM_INVALID;
+      do_in_main_thread(FROM_HERE, base::BindOnce(btif_ble_transmitter_test,
+                                                  buf[0], buf[1], buf[2]));
+      break;
+    case HCI_BLE_RECEIVER_TEST:
+      if (len != 1) return BT_STATUS_PARM_INVALID;
+      do_in_main_thread(FROM_HERE,
+                        base::BindOnce(btif_ble_receiver_test, buf[0]));
+      break;
+    case HCI_BLE_TEST_END:
+      do_in_main_thread(FROM_HERE, base::BindOnce(btif_ble_test_end));
+      break;
+    default:
+      return BT_STATUS_UNSUPPORTED;
+  }
+  return BT_STATUS_SUCCESS;
+}
+
 static bt_os_callouts_t* wakelock_os_callouts_saved = nullptr;
 
 static int acquire_wake_lock_cb(const char* lock_name) {
@@ -1136,6 +1160,7 @@
     .get_profile_interface = get_profile_interface,
     .dut_mode_configure = dut_mode_configure,
     .dut_mode_send = dut_mode_send,
+    .le_test_mode = le_test_mode,
     .set_os_callouts = set_os_callouts,
     .read_energy_info = read_energy_info,
     .dump = dump,
@@ -1408,6 +1433,15 @@
                                   event));
 }
 
+void invoke_le_test_mode_cb(bt_status_t status, uint16_t count) {
+  do_in_jni_thread(FROM_HERE, base::BindOnce(
+                                  [](bt_status_t status, uint16_t count) {
+                                    HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
+                                              status, count);
+                                  },
+                                  status, count));
+}
+
 // takes ownership of |uid_data|
 void invoke_energy_info_cb(bt_activity_energy_info energy_info,
                            bt_uid_traffic_t* uid_data) {
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index c242232..a77e6c6 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -3691,6 +3691,44 @@
   btif_update_remote_properties(bd_addr, bd_name, dev_class, dev_type);
 }
 
+static void btif_dm_ble_tx_test_cback(void* p) {
+  char* p_param = (char*)p;
+  uint8_t status;
+  STREAM_TO_UINT8(status, p_param);
+  GetInterfaceToProfiles()->events->invoke_le_test_mode_cb(
+      (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
+}
+
+static void btif_dm_ble_rx_test_cback(void* p) {
+  char* p_param = (char*)p;
+  uint8_t status;
+  STREAM_TO_UINT8(status, p_param);
+  GetInterfaceToProfiles()->events->invoke_le_test_mode_cb(
+      (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
+}
+
+static void btif_dm_ble_test_end_cback(void* p) {
+  char* p_param = (char*)p;
+  uint8_t status;
+  uint16_t count = 0;
+  STREAM_TO_UINT8(status, p_param);
+  if (status == 0) STREAM_TO_UINT16(count, p_param);
+  GetInterfaceToProfiles()->events->invoke_le_test_mode_cb(
+      (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, count);
+}
+
+void btif_ble_transmitter_test(uint8_t tx_freq, uint8_t test_data_len,
+                               uint8_t packet_payload) {
+  BTM_BleTransmitterTest(tx_freq, test_data_len, packet_payload,
+                         btif_dm_ble_tx_test_cback);
+}
+
+void btif_ble_receiver_test(uint8_t rx_freq) {
+  BTM_BleReceiverTest(rx_freq, btif_dm_ble_rx_test_cback);
+}
+
+void btif_ble_test_end() { BTM_BleTestEnd(btif_dm_ble_test_end_cback); }
+
 void btif_dm_on_disable() {
   /* cancel any pending pairing requests */
   if (is_bonding_or_sdp()) {
diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc
index ab37b95..04f0299 100644
--- a/system/btif/test/btif_core_test.cc
+++ b/system/btif/test/btif_core_test.cc
@@ -86,6 +86,7 @@
                                   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 le_test_mode_callback(bt_status_t status, uint16_t num_packets) {}
 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,
@@ -109,6 +110,7 @@
     .acl_state_changed_cb = acl_state_changed_callback,
     .thread_evt_cb = callback_thread_event,
     .dut_mode_recv_cb = dut_mode_recv_callback,
+    .le_test_mode_cb = le_test_mode_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 de215c2..6b367f2 100644
--- a/system/btif/test/btif_hh_test.cc
+++ b/system/btif/test/btif_hh_test.cc
@@ -134,6 +134,7 @@
     .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
+    .le_test_mode_cb = nullptr,             // le_test_mode_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 0973d8a..30edb0f 100644
--- a/system/gd/rust/topshim/src/btif.rs
+++ b/system/gd/rust/topshim/src/btif.rs
@@ -885,6 +885,7 @@
     // Unimplemented so far:
     // thread_evt_cb
     // dut_mode_recv_cb
+    // le_test_mode_cb
     // energy_info_cb
     // link_quality_report_cb
     // switch_buffer_size_cb
@@ -1072,6 +1073,7 @@
             acl_state_changed_cb: Some(acl_state_cb),
             thread_evt_cb: None,
             dut_mode_recv_cb: None,
+            le_test_mode_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 031ce22..00396f9 100644
--- a/system/include/hardware/bluetooth.h
+++ b/system/include/hardware/bluetooth.h
@@ -550,6 +550,12 @@
 typedef void (*dut_mode_recv_callback)(uint16_t opcode, uint8_t* buf,
                                        uint8_t len);
 
+/* LE Test mode callbacks
+ * This callback shall be invoked whenever the le_tx_test, le_rx_test or
+ * le_test_end is invoked The num_packets is valid only for le_test_end command
+ */
+typedef void (*le_test_mode_callback)(bt_status_t status, uint16_t num_packets);
+
 /** 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
@@ -585,6 +591,7 @@
   acl_state_changed_callback acl_state_changed_cb;
   callback_thread_event thread_evt_cb;
   dut_mode_recv_callback dut_mode_recv_cb;
+  le_test_mode_callback le_test_mode_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;
@@ -744,6 +751,10 @@
   /* 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);
+  /** BLE Test Mode APIs */
+  /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End
+   */
+  int (*le_test_mode)(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.cc b/system/main/shim/btm_api.cc
index b377a03..aef03ed 100644
--- a/system/main/shim/btm_api.cc
+++ b/system/main/shim/btm_api.cc
@@ -600,6 +600,25 @@
   return false;
 }
 
+void bluetooth::shim::BTM_BleReceiverTest(uint8_t rx_freq,
+                                          tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  LOG_INFO("UNIMPLEMENTED %s", __func__);
+  CHECK(p_cmd_cmpl_cback != nullptr);
+}
+
+void bluetooth::shim::BTM_BleTransmitterTest(uint8_t tx_freq,
+                                             uint8_t test_data_len,
+                                             uint8_t packet_payload,
+                                             tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  LOG_INFO("UNIMPLEMENTED %s", __func__);
+  CHECK(p_cmd_cmpl_cback != nullptr);
+}
+
+void bluetooth::shim::BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  LOG_INFO("UNIMPLEMENTED %s", __func__);
+  CHECK(p_cmd_cmpl_cback != nullptr);
+}
+
 bool bluetooth::shim::BTM_GetLeSecurityState(const RawAddress& bd_addr,
                                              uint8_t* p_le_dev_sec_flags,
                                              uint8_t* p_le_key_size) {
diff --git a/system/main/shim/btm_api.h b/system/main/shim/btm_api.h
index e14eb4a2..aa2996c 100644
--- a/system/main/shim/btm_api.h
+++ b/system/main/shim/btm_api.h
@@ -553,6 +553,46 @@
 
 /*******************************************************************************
  *
+ * Function         BTM_BleReceiverTest
+ *
+ * Description      This function is called to start the LE Receiver test
+ *
+ * Parameter       rx_freq - Frequency Range
+ *               p_cmd_cmpl_cback - Command Complete callback
+ *
+ ******************************************************************************/
+void BTM_BleReceiverTest(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback);
+
+/*******************************************************************************
+ *
+ * Function         BTM_BleTransmitterTest
+ *
+ * Description      This function is called to start the LE Transmitter test
+ *
+ * Parameter       tx_freq - Frequency Range
+ *                       test_data_len - Length in bytes of payload data in each
+ *                                       packet
+ *                       packet_payload - Pattern to use in the payload
+ *                       p_cmd_cmpl_cback - Command Complete callback
+ *
+ ******************************************************************************/
+void BTM_BleTransmitterTest(uint8_t tx_freq, uint8_t test_data_len,
+                            uint8_t packet_payload,
+                            tBTM_CMPL_CB* p_cmd_cmpl_cback);
+
+/*******************************************************************************
+ *
+ * Function         BTM_BleTestEnd
+ *
+ * Description     This function is called to stop the in-progress TX or RX test
+ *
+ * Parameter       p_cmd_cmpl_cback - Command complete callback
+ *
+ ******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback);
+
+/*******************************************************************************
+ *
  * Function         BTM_UseLeLink
  *
  * Description      Select the underlying physical link to use.
diff --git a/system/stack/btm/btm_ble.cc b/system/stack/btm/btm_ble.cc
index 4d38297..7931bef 100644
--- a/system/stack/btm/btm_ble.cc
+++ b/system/stack/btm/btm_ble.cc
@@ -564,6 +564,81 @@
 
 /*******************************************************************************
  *
+ * Function         BTM_BleReceiverTest
+ *
+ * Description      This function is called to start the LE Receiver test
+ *
+ * Parameter       rx_freq - Frequency Range
+ *               p_cmd_cmpl_cback - Command Complete callback
+ *
+ ******************************************************************************/
+void BTM_BleReceiverTest(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  if (bluetooth::shim::is_gd_shim_enabled()) {
+    return bluetooth::shim::BTM_BleReceiverTest(rx_freq, p_cmd_cmpl_cback);
+  }
+  btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+  btsnd_hcic_ble_receiver_test(rx_freq);
+}
+
+/*******************************************************************************
+ *
+ * Function         BTM_BleTransmitterTest
+ *
+ * Description      This function is called to start the LE Transmitter test
+ *
+ * Parameter       tx_freq - Frequency Range
+ *                       test_data_len - Length in bytes of payload data in each
+ *                                       packet
+ *                       packet_payload - Pattern to use in the payload
+ *                       p_cmd_cmpl_cback - Command Complete callback
+ *
+ ******************************************************************************/
+void BTM_BleTransmitterTest(uint8_t tx_freq, uint8_t test_data_len,
+                            uint8_t packet_payload,
+                            tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  if (bluetooth::shim::is_gd_shim_enabled()) {
+    return bluetooth::shim::BTM_BleTransmitterTest(
+        tx_freq, test_data_len, packet_payload, p_cmd_cmpl_cback);
+  }
+  btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+  btsnd_hcic_ble_transmitter_test(tx_freq, test_data_len, packet_payload);
+}
+
+/*******************************************************************************
+ *
+ * Function         BTM_BleTestEnd
+ *
+ * Description      This function is called to stop the in-progress TX or RX
+ *                  test
+ *
+ * Parameter       p_cmd_cmpl_cback - Command complete callback
+ *
+ ******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  if (bluetooth::shim::is_gd_shim_enabled()) {
+    return bluetooth::shim::BTM_BleTestEnd(p_cmd_cmpl_cback);
+  }
+  btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+  btsnd_hcic_ble_test_end();
+}
+
+/*******************************************************************************
+ * Internal Functions
+ ******************************************************************************/
+void btm_ble_test_command_complete(uint8_t* p) {
+  tBTM_CMPL_CB* p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
+
+  btm_cb.devcb.p_le_test_cmd_cmpl_cb = NULL;
+
+  if (p_cb) {
+    (*p_cb)(p);
+  }
+}
+
+/*******************************************************************************
+ *
  * Function         BTM_UseLeLink
  *
  * Description      This function is to select the underlying physical link to
diff --git a/system/stack/btm/btm_int_types.h b/system/stack/btm/btm_int_types.h
index b5785e7..b61f088 100644
--- a/system/stack/btm/btm_int_types.h
+++ b/system/stack/btm/btm_int_types.h
@@ -165,6 +165,10 @@
 
   DEV_CLASS dev_class; /* Local device class                   */
 
+  tBTM_CMPL_CB*
+      p_le_test_cmd_cmpl_cb; /* Callback function to be called when
+                             LE test mode command has been sent successfully */
+
   RawAddress read_tx_pwr_addr; /* read TX power target address     */
 
   tBTM_BLE_LOCAL_ID_KEYS id_keys;   /* local BLE ID keys */
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index 790b7e5..91cb62e 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -1139,6 +1139,12 @@
       LOG(ERROR) << "No command complete expected, but received!";
       break;
 
+    case HCI_BLE_TRANSMITTER_TEST:
+    case HCI_BLE_RECEIVER_TEST:
+    case HCI_BLE_TEST_END:
+      btm_ble_test_command_complete(p);
+      break;
+
     case HCI_BLE_ADD_DEV_RESOLVING_LIST:
       btm_ble_add_resolving_list_entry_complete(p, evt_len);
       break;
diff --git a/system/stack/hcic/hciblecmds.cc b/system/stack/hcic/hciblecmds.cc
index 7a363a8..0a2ad2e 100644
--- a/system/stack/hcic/hciblecmds.cc
+++ b/system/stack/hcic/hciblecmds.cc
@@ -460,6 +460,52 @@
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
+void btsnd_hcic_ble_receiver_test(uint8_t rx_freq) {
+  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_WRITE_PARAM1;
+  p->offset = 0;
+
+  UINT16_TO_STREAM(pp, HCI_BLE_RECEIVER_TEST);
+  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1);
+
+  UINT8_TO_STREAM(pp, rx_freq);
+
+  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+}
+
+void btsnd_hcic_ble_transmitter_test(uint8_t tx_freq, uint8_t test_data_len,
+                                     uint8_t payload) {
+  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_WRITE_PARAM3;
+  p->offset = 0;
+
+  UINT16_TO_STREAM(pp, HCI_BLE_TRANSMITTER_TEST);
+  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM3);
+
+  UINT8_TO_STREAM(pp, tx_freq);
+  UINT8_TO_STREAM(pp, test_data_len);
+  UINT8_TO_STREAM(pp, payload);
+
+  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+}
+
+void btsnd_hcic_ble_test_end(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_BLE_TEST_END);
+  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_CMD);
+
+  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+}
+
 void btsnd_hcic_ble_read_host_supported(void) {
   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_ble_api.h b/system/stack/include/btm_ble_api.h
index dadfdaf..6136142 100644
--- a/system/stack/include/btm_ble_api.h
+++ b/system/stack/include/btm_ble_api.h
@@ -523,6 +523,46 @@
 
 /*******************************************************************************
  *
+ * Function         BTM_BleReceiverTest
+ *
+ * Description      This function is called to start the LE Receiver test
+ *
+ * Parameter       rx_freq - Frequency Range
+ *               p_cmd_cmpl_cback - Command Complete callback
+ *
+ ******************************************************************************/
+void BTM_BleReceiverTest(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback);
+
+/*******************************************************************************
+ *
+ * Function         BTM_BleTransmitterTest
+ *
+ * Description      This function is called to start the LE Transmitter test
+ *
+ * Parameter       tx_freq - Frequency Range
+ *                       test_data_len - Length in bytes of payload data in each
+ *                                       packet
+ *                       packet_payload - Pattern to use in the payload
+ *                       p_cmd_cmpl_cback - Command Complete callback
+ *
+ ******************************************************************************/
+void BTM_BleTransmitterTest(uint8_t tx_freq, uint8_t test_data_len,
+                            uint8_t packet_payload,
+                            tBTM_CMPL_CB* p_cmd_cmpl_cback);
+
+/*******************************************************************************
+ *
+ * Function         BTM_BleTestEnd
+ *
+ * Description     This function is called to stop the in-progress TX or RX test
+ *
+ * Parameter       p_cmd_cmpl_cback - Command complete callback
+ *
+ ******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback);
+
+/*******************************************************************************
+ *
  * Function         BTM_UseLeLink
  *
  * Description      Select the underlying physical link to use.
diff --git a/system/stack/include/hcimsgs.h b/system/stack/include/hcimsgs.h
index 675c64e..a41ae43 100644
--- a/system/stack/include/hcimsgs.h
+++ b/system/stack/include/hcimsgs.h
@@ -372,6 +372,12 @@
 
 void btsnd_hcic_ble_read_host_supported(void);
 
+void btsnd_hcic_ble_receiver_test(uint8_t rx_freq);
+
+void btsnd_hcic_ble_transmitter_test(uint8_t tx_freq, uint8_t test_data_len,
+                                     uint8_t payload);
+void btsnd_hcic_ble_test_end(void);
+
 void btsnd_hcic_ble_rc_param_req_reply(uint16_t handle, uint16_t conn_int_min,
                                        uint16_t conn_int_max,
                                        uint16_t conn_latency,
diff --git a/system/test/common/core_interface.cc b/system/test/common/core_interface.cc
index f0b8235..e20df2c 100644
--- a/system/test/common/core_interface.cc
+++ b/system/test/common/core_interface.cc
@@ -36,6 +36,7 @@
     .invoke_le_address_associate_cb = invoke_le_address_associate_cb,
     .invoke_acl_state_changed_cb = invoke_acl_state_changed_cb,
     .invoke_thread_evt_cb = invoke_thread_evt_cb,
+    .invoke_le_test_mode_cb = invoke_le_test_mode_cb,
     .invoke_energy_info_cb = invoke_energy_info_cb,
     .invoke_link_quality_report_cb = invoke_link_quality_report_cb};
 
diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc
index 551a6d6..9006afd 100644
--- a/system/test/headless/headless.cc
+++ b/system/test/headless/headless.cc
@@ -205,6 +205,11 @@
   LOG_INFO("%s", __func__);
 }
 
+void le_test_mode([[maybe_unused]] bt_status_t status,
+                  [[maybe_unused]] uint16_t num_packets) {
+  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__);
@@ -226,6 +231,7 @@
     .acl_state_changed_cb = acl_state_changed,
     .thread_evt_cb = thread_event,
     .dut_mode_recv_cb = dut_mode_recv,
+    .le_test_mode_cb = le_test_mode,
     .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_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc
index cd0f805..412214c 100644
--- a/system/test/mock/mock_bluetooth_interface.cc
+++ b/system/test/mock/mock_bluetooth_interface.cc
@@ -50,6 +50,9 @@
                                  bt_conn_direction_t direction,
                                  uint16_t acl_handle) {}
 void invoke_thread_evt_cb(bt_cb_thread_evt event) {}
+
+void invoke_le_test_mode_cb(bt_status_t status, uint16_t count) {}
+
 void invoke_energy_info_cb(bt_activity_energy_info energy_info,
                            bt_uid_traffic_t* uid_data) {}
 void invoke_link_quality_report_cb(uint64_t timestamp, int report_id, int rssi,
diff --git a/system/test/mock/mock_btif_bluetooth.cc b/system/test/mock/mock_btif_bluetooth.cc
index a599472..0a9de74 100644
--- a/system/test/mock/mock_btif_bluetooth.cc
+++ b/system/test/mock/mock_btif_bluetooth.cc
@@ -52,6 +52,7 @@
 struct get_remote_device_properties get_remote_device_properties;
 struct get_remote_device_property get_remote_device_property;
 struct get_remote_services get_remote_services;
+struct le_test_mode le_test_mode;
 struct set_remote_device_property set_remote_device_property;
 struct set_hal_cbacks set_hal_cbacks;
 
@@ -99,6 +100,10 @@
   inc_func_call_count(__func__);
   return test::mock::btif_bluetooth::get_remote_services(remote_addr);
 }
+int le_test_mode(uint16_t opcode, uint8_t* buf, uint8_t len) {
+  inc_func_call_count(__func__);
+  return test::mock::btif_bluetooth::le_test_mode(opcode, buf, len);
+}
 int set_remote_device_property(RawAddress* remote_addr,
                                const bt_property_t* property) {
   inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_btif_bluetooth.h b/system/test/mock/mock_btif_bluetooth.h
index c007631..6535fb2 100644
--- a/system/test/mock/mock_btif_bluetooth.h
+++ b/system/test/mock/mock_btif_bluetooth.h
@@ -128,6 +128,17 @@
   int operator()(RawAddress* remote_addr) { return body(remote_addr); };
 };
 extern struct get_remote_services get_remote_services;
+// Name: le_test_mode
+// Params: uint16_t opcode, uint8_t* buf, uint8_t len
+// Returns: int
+struct le_test_mode {
+  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 le_test_mode le_test_mode;
 // Name: set_remote_device_property
 // Params: RawAddress* remote_addr, const bt_property_t* property
 // Returns: int
diff --git a/system/test/mock/mock_btif_dm.cc b/system/test/mock/mock_btif_dm.cc
index 0559729..556cbe4 100644
--- a/system/test/mock/mock_btif_dm.cc
+++ b/system/test/mock/mock_btif_dm.cc
@@ -69,6 +69,12 @@
 void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) {
   inc_func_call_count(__func__);
 }
+void btif_ble_receiver_test(uint8_t rx_freq) { inc_func_call_count(__func__); }
+void btif_ble_test_end() { inc_func_call_count(__func__); }
+void btif_ble_transmitter_test(uint8_t tx_freq, uint8_t test_data_len,
+                               uint8_t packet_payload) {
+  inc_func_call_count(__func__);
+}
 void btif_debug_bond_event_dump(int fd) { inc_func_call_count(__func__); }
 void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req, bool is_consent) {
   inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_main_shim_btm_api.cc b/system/test/mock/mock_main_shim_btm_api.cc
index 2cf7689..884278b 100644
--- a/system/test/mock/mock_main_shim_btm_api.cc
+++ b/system/test/mock/mock_main_shim_btm_api.cc
@@ -271,6 +271,10 @@
     base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
   inc_func_call_count(__func__);
 }
+void bluetooth::shim::BTM_BleReceiverTest(uint8_t rx_freq,
+                                          tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  inc_func_call_count(__func__);
+}
 void bluetooth::shim::BTM_BleSecureConnectionOobDataReply(
     const RawAddress& bd_addr, uint8_t* p_c, uint8_t* p_r) {
   inc_func_call_count(__func__);
@@ -290,6 +294,15 @@
                                                uint16_t supervision_tout) {
   inc_func_call_count(__func__);
 }
+void bluetooth::shim::BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  inc_func_call_count(__func__);
+}
+void bluetooth::shim::BTM_BleTransmitterTest(uint8_t tx_freq,
+                                             uint8_t test_data_len,
+                                             uint8_t packet_payload,
+                                             tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  inc_func_call_count(__func__);
+}
 void bluetooth::shim::BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) {
   inc_func_call_count(__func__);
 }
diff --git a/system/test/mock/mock_stack_btm_ble.cc b/system/test/mock/mock_stack_btm_ble.cc
index b52c05b..f9b115e 100644
--- a/system/test/mock/mock_stack_btm_ble.cc
+++ b/system/test/mock/mock_stack_btm_ble.cc
@@ -43,9 +43,12 @@
 struct BTM_BleOobDataReply BTM_BleOobDataReply;
 struct BTM_BlePasskeyReply BTM_BlePasskeyReply;
 struct BTM_BleReadPhy BTM_BleReadPhy;
+struct BTM_BleReceiverTest BTM_BleReceiverTest;
 struct BTM_BleSecureConnectionOobDataReply BTM_BleSecureConnectionOobDataReply;
 struct BTM_BleSetPhy BTM_BleSetPhy;
 struct BTM_BleSetPrefConnParams BTM_BleSetPrefConnParams;
+struct BTM_BleTestEnd BTM_BleTestEnd;
+struct BTM_BleTransmitterTest BTM_BleTransmitterTest;
 struct BTM_BleVerifySignature BTM_BleVerifySignature;
 struct BTM_GetDeviceDHK BTM_GetDeviceDHK;
 struct BTM_GetDeviceEncRoot BTM_GetDeviceEncRoot;
@@ -160,6 +163,10 @@
   inc_func_call_count(__func__);
   test::mock::stack_btm_ble::BTM_BleReadPhy(bd_addr, cb);
 }
+void BTM_BleReceiverTest(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  inc_func_call_count(__func__);
+  test::mock::stack_btm_ble::BTM_BleReceiverTest(rx_freq, p_cmd_cmpl_cback);
+}
 void BTM_BleSecureConnectionOobDataReply(const RawAddress& bd_addr,
                                          uint8_t* p_c, uint8_t* p_r) {
   inc_func_call_count(__func__);
@@ -181,6 +188,17 @@
       bd_addr, min_conn_int, max_conn_int, peripheral_latency,
       supervision_tout);
 }
+void BTM_BleTestEnd(tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  inc_func_call_count(__func__);
+  test::mock::stack_btm_ble::BTM_BleTestEnd(p_cmd_cmpl_cback);
+}
+void BTM_BleTransmitterTest(uint8_t tx_freq, uint8_t test_data_len,
+                            uint8_t packet_payload,
+                            tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+  inc_func_call_count(__func__);
+  test::mock::stack_btm_ble::BTM_BleTransmitterTest(
+      tx_freq, test_data_len, packet_payload, p_cmd_cmpl_cback);
+}
 bool BTM_BleVerifySignature(const RawAddress& bd_addr, uint8_t* p_orig,
                             uint16_t len, uint32_t counter, uint8_t* p_comp) {
   inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_stack_btm_ble.h b/system/test/mock/mock_stack_btm_ble.h
index 6db8653..1699a9c 100644
--- a/system/test/mock/mock_stack_btm_ble.h
+++ b/system/test/mock/mock_stack_btm_ble.h
@@ -156,6 +156,18 @@
 };
 extern struct BTM_BleReadPhy BTM_BleReadPhy;
 
+// Name: BTM_BleReceiverTest
+// Params: uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback
+// Return: void
+struct BTM_BleReceiverTest {
+  std::function<void(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback)> body{
+      [](uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback) {}};
+  void operator()(uint8_t rx_freq, tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+    body(rx_freq, p_cmd_cmpl_cback);
+  };
+};
+extern struct BTM_BleReceiverTest BTM_BleReceiverTest;
+
 // Name: BTM_BleSecureConnectionOobDataReply
 // Params: const RawAddress& bd_addr, uint8_t* p_c, uint8_t* p_r
 // Return: void
@@ -204,6 +216,31 @@
 };
 extern struct BTM_BleSetPrefConnParams BTM_BleSetPrefConnParams;
 
+// Name: BTM_BleTestEnd
+// Params: tBTM_CMPL_CB* p_cmd_cmpl_cback
+// Return: void
+struct BTM_BleTestEnd {
+  std::function<void(tBTM_CMPL_CB* p_cmd_cmpl_cback)> body{
+      [](tBTM_CMPL_CB* p_cmd_cmpl_cback) {}};
+  void operator()(tBTM_CMPL_CB* p_cmd_cmpl_cback) { body(p_cmd_cmpl_cback); };
+};
+extern struct BTM_BleTestEnd BTM_BleTestEnd;
+
+// Name: BTM_BleTransmitterTest
+// Params: uint8_t tx_freq, uint8_t test_data_len, uint8_t packet_payload,
+// tBTM_CMPL_CB* p_cmd_cmpl_cback Return: void
+struct BTM_BleTransmitterTest {
+  std::function<void(uint8_t tx_freq, uint8_t test_data_len,
+                     uint8_t packet_payload, tBTM_CMPL_CB* p_cmd_cmpl_cback)>
+      body{[](uint8_t tx_freq, uint8_t test_data_len, uint8_t packet_payload,
+              tBTM_CMPL_CB* p_cmd_cmpl_cback) {}};
+  void operator()(uint8_t tx_freq, uint8_t test_data_len,
+                  uint8_t packet_payload, tBTM_CMPL_CB* p_cmd_cmpl_cback) {
+    body(tx_freq, test_data_len, packet_payload, p_cmd_cmpl_cback);
+  };
+};
+extern struct BTM_BleTransmitterTest BTM_BleTransmitterTest;
+
 // Name: BTM_BleVerifySignature
 // Params: const RawAddress& bd_addr, uint8_t* p_orig, uint16_t len, uint32_t
 // counter, uint8_t* p_comp Return: bool
diff --git a/system/test/mock/mock_stack_hcic_hciblecmds.cc b/system/test/mock/mock_stack_hcic_hciblecmds.cc
index 37add12..605f287 100644
--- a/system/test/mock/mock_stack_hcic_hciblecmds.cc
+++ b/system/test/mock/mock_stack_hcic_hciblecmds.cc
@@ -75,6 +75,7 @@
     btsnd_hcic_ble_read_resolvable_addr_local;
 struct btsnd_hcic_ble_read_resolvable_addr_peer
     btsnd_hcic_ble_read_resolvable_addr_peer;
+struct btsnd_hcic_ble_receiver_test btsnd_hcic_ble_receiver_test;
 struct btsnd_hcic_ble_set_addr_resolution_enable
     btsnd_hcic_ble_set_addr_resolution_enable;
 struct btsnd_hcic_ble_set_adv_data btsnd_hcic_ble_set_adv_data;
@@ -100,6 +101,8 @@
 struct btsnd_hcic_ble_set_scan_params btsnd_hcic_ble_set_scan_params;
 struct btsnd_hcic_ble_set_scan_rsp_data btsnd_hcic_ble_set_scan_rsp_data;
 struct btsnd_hcic_ble_start_enc btsnd_hcic_ble_start_enc;
+struct btsnd_hcic_ble_test_end btsnd_hcic_ble_test_end;
+struct btsnd_hcic_ble_transmitter_test btsnd_hcic_ble_transmitter_test;
 struct btsnd_hcic_ble_upd_ll_conn_params btsnd_hcic_ble_upd_ll_conn_params;
 struct btsnd_hcic_ble_write_adv_params btsnd_hcic_ble_write_adv_params;
 struct btsnd_hcic_create_big btsnd_hcic_create_big;
@@ -300,6 +303,10 @@
   test::mock::stack_hcic_hciblecmds::btsnd_hcic_ble_read_resolvable_addr_peer(
       addr_type_peer, bda_peer);
 }
+void btsnd_hcic_ble_receiver_test(uint8_t rx_freq) {
+  inc_func_call_count(__func__);
+  test::mock::stack_hcic_hciblecmds::btsnd_hcic_ble_receiver_test(rx_freq);
+}
 void btsnd_hcic_ble_set_addr_resolution_enable(uint8_t addr_resolution_enable) {
   inc_func_call_count(__func__);
   test::mock::stack_hcic_hciblecmds::btsnd_hcic_ble_set_addr_resolution_enable(
@@ -411,6 +418,16 @@
   test::mock::stack_hcic_hciblecmds::btsnd_hcic_ble_start_enc(handle, rand,
                                                               ediv, ltk);
 }
+void btsnd_hcic_ble_test_end(void) {
+  inc_func_call_count(__func__);
+  test::mock::stack_hcic_hciblecmds::btsnd_hcic_ble_test_end();
+}
+void btsnd_hcic_ble_transmitter_test(uint8_t tx_freq, uint8_t test_data_len,
+                                     uint8_t payload) {
+  inc_func_call_count(__func__);
+  test::mock::stack_hcic_hciblecmds::btsnd_hcic_ble_transmitter_test(
+      tx_freq, test_data_len, payload);
+}
 void btsnd_hcic_ble_upd_ll_conn_params(uint16_t handle, uint16_t conn_int_min,
                                        uint16_t conn_int_max,
                                        uint16_t conn_latency,
diff --git a/system/test/mock/mock_stack_hcic_hciblecmds.h b/system/test/mock/mock_stack_hcic_hciblecmds.h
index 0f374b3..9e32f07 100644
--- a/system/test/mock/mock_stack_hcic_hciblecmds.h
+++ b/system/test/mock/mock_stack_hcic_hciblecmds.h
@@ -464,6 +464,16 @@
 };
 extern struct btsnd_hcic_ble_read_resolvable_addr_peer
     btsnd_hcic_ble_read_resolvable_addr_peer;
+
+// Name: btsnd_hcic_ble_receiver_test
+// Params: uint8_t rx_freq
+// Return: void
+struct btsnd_hcic_ble_receiver_test {
+  std::function<void(uint8_t rx_freq)> body{[](uint8_t rx_freq) {}};
+  void operator()(uint8_t rx_freq) { body(rx_freq); };
+};
+extern struct btsnd_hcic_ble_receiver_test btsnd_hcic_ble_receiver_test;
+
 // Name: btsnd_hcic_ble_rm_device_resolving_list
 // Params: uint8_t addr_type_peer, const RawAddress& bda_peer
 // Return: void
@@ -721,6 +731,27 @@
 };
 extern struct btsnd_hcic_ble_start_enc btsnd_hcic_ble_start_enc;
 
+// Name: btsnd_hcic_ble_test_end
+// Params: void
+// Return: void
+struct btsnd_hcic_ble_test_end {
+  std::function<void(void)> body{[](void) {}};
+  void operator()(void) { body(); };
+};
+extern struct btsnd_hcic_ble_test_end btsnd_hcic_ble_test_end;
+
+// Name: btsnd_hcic_ble_transmitter_test
+// Params: uint8_t tx_freq, uint8_t test_data_len, uint8_t payload
+// Return: void
+struct btsnd_hcic_ble_transmitter_test {
+  std::function<void(uint8_t tx_freq, uint8_t test_data_len, uint8_t payload)>
+      body{[](uint8_t tx_freq, uint8_t test_data_len, uint8_t payload) {}};
+  void operator()(uint8_t tx_freq, uint8_t test_data_len, uint8_t payload) {
+    body(tx_freq, test_data_len, payload);
+  };
+};
+extern struct btsnd_hcic_ble_transmitter_test btsnd_hcic_ble_transmitter_test;
+
 // Name: btsnd_hcic_ble_upd_ll_conn_params
 // Params: uint16_t handle, uint16_t conn_int_min, uint16_t conn_int_max,
 // uint16_t conn_latency, uint16_t conn_timeout, uint16_t min_ce_len, uint16_t