Revert "HCI HAL: HCI Proxy Audio Software offload integration"

This reverts commit b833bc6e61837b6cf1cab5c58c4f7d17167b23dc.

Change-Id: I3b10dc8b4e088993c3fde0ddb3ed619b2eea8837
diff --git a/bluetooth/aidl/Android.bp b/bluetooth/aidl/Android.bp
index 4ee2f49..0daecf7 100644
--- a/bluetooth/aidl/Android.bp
+++ b/bluetooth/aidl/Android.bp
@@ -16,6 +16,13 @@
     srcs: ["android/hardware/bluetooth/*.aidl"],
     stability: "vintf",
     backend: {
+        cpp: {
+            // FIXME should this be disabled?
+            // prefer NDK backend which can be used anywhere
+            // If you disable this, you also need to delete the C++
+            // translate code.
+            enabled: true,
+        },
         rust: {
             enabled: true,
         },
@@ -37,4 +44,5 @@
         },
     ],
     frozen: true,
+
 }
diff --git a/bluetooth/aidl/default/Android.bp b/bluetooth/aidl/default/Android.bp
index d3f6364..3f4ba99 100644
--- a/bluetooth/aidl/default/Android.bp
+++ b/bluetooth/aidl/default/Android.bp
@@ -2,62 +2,81 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-cc_library_static {
-    name: "libbluetoothhcihalimpl",
-    vendor_available: true,
-    host_supported: true,
-    srcs: [
-        "BluetoothHci.cpp",
-        "net_bluetooth_mgmt.cpp",
-    ],
+cc_defaults {
+    name: "android.hardware.bluetooth-service-build-defaults",
     cflags: [
         "-Wall",
         "-Wextra",
     ],
-    header_libs: [
-        "libbluetooth_offload_hal_headers",
+    shared_libs: [
+        "android.hardware.bluetooth-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libutils",
     ],
     static_libs: [
         "android.hardware.bluetooth.async",
         "android.hardware.bluetooth.hci",
     ],
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "liblog",
-        "libutils",
+}
+
+cc_library_static {
+    name: "libbluetoothhcihalimpl",
+    vendor_available: true,
+    host_supported: true,
+    defaults: ["android.hardware.bluetooth-service-build-defaults"],
+    srcs: [
+        "BluetoothHci.cpp",
+        "net_bluetooth_mgmt.cpp",
     ],
 }
 
-rust_binary {
+cc_binary {
     name: "android.hardware.bluetooth-service.default",
-    crate_name: "bluetooth_hci_hal_server",
     relative_install_path: "hw",
     init_rc: ["bluetooth-service-default.rc"],
     vintf_fragments: [":manifest_android.hardware.bluetooth-service.default.xml"],
     vendor: true,
-    prefer_rlib: true,
-    srcs: ["main.rs"],
-    rustlibs: [
-        "android.hardware.bluetooth-V1-rust",
-        "libbluetooth_offload_hal",
-        "libbluetooth_offload_leaudio_hci",
-        "libbinder_rs",
-        "liblogger",
-        "liblog_rust",
+    defaults: ["android.hardware.bluetooth-service-build-defaults"],
+    srcs: [
+        "service.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.bluetooth-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+        "libhidlbase",
+        "libutils",
+        "liblog",
+    ],
+    static_libs: [
+        "libbluetoothhcihalimpl",
+    ],
+}
+
+cc_fuzz {
+    name: "android.hardware.bluetooth-service.default_fuzzer",
+    host_supported: true,
+    defaults: ["service_fuzzer_defaults"],
+    srcs: [
+        "test/fuzzer.cpp",
     ],
     static_libs: [
         "android.hardware.bluetooth.async",
         "android.hardware.bluetooth.hci",
+        "android.hardware.bluetooth-V1-ndk",
         "libbluetoothhcihalimpl",
-    ],
-    shared_libs: [
-        "libbase",
-        "libc++",
-        "libcutils",
         "liblog",
-        "libutils",
     ],
+    fuzz_config: {
+        componentid: 27441,
+        cc: [
+            "mylesgw@google.com",
+        ],
+    },
 }
 
 filegroup {
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index bcdb67e..a247cb0 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,20 +16,18 @@
 
 #define LOG_TAG "android.hardware.bluetooth.service.default"
 
+#include "BluetoothHci.h"
+
 #include <cutils/properties.h>
 #include <fcntl.h>
-#include <hal/ffi.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
 #include <string.h>
+#include <sys/uio.h>
 #include <termios.h>
 
-#include <future>
-#include <memory>
-#include <vector>
-
-#include "async_fd_watcher.h"
-#include "h4_protocol.h"
 #include "log/log.h"
-#include "net_bluetooth_mgmt.h"
 
 namespace {
 int SetTerminalRaw(int fd) {
@@ -46,9 +44,12 @@
 
 using namespace ::android::hardware::bluetooth::hci;
 using namespace ::android::hardware::bluetooth::async;
+using aidl::android::hardware::bluetooth::Status;
 
 namespace aidl::android::hardware::bluetooth::impl {
 
+void OnDeath(void* cookie);
+
 std::optional<std::string> GetSystemProperty(const std::string& property) {
   std::array<char, PROPERTY_VALUE_MAX> value_array{0};
   auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
@@ -62,298 +63,302 @@
   return str.compare(0, prefix.length(), prefix) == 0;
 }
 
-class Hal {
+class BluetoothDeathRecipient {
  public:
-  Hal(const std::string& dev_path = "/dev/hvc5") {
-    char property_bytes[PROPERTY_VALUE_MAX];
-    property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
-    mDevPath = std::string(property_bytes);
+  BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
+
+  void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
+    mCb = cb;
+    clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
+    auto linkToDeathReturnStatus = AIBinder_linkToDeath(
+        mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
+    LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
+                        "Unable to link to death recipient");
   }
 
-  static void Initialize(void* instance,
-                         const struct hal_callbacks* callbacks) {
-    static_cast<Hal*>(instance)->Initialize(callbacks);
+  void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
+    LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
   }
 
-  static void Close(void* instance) { static_cast<Hal*>(instance)->Close(); }
-
-  static void SendCommand(void* instance, const uint8_t* data, size_t len) {
-    static_cast<Hal*>(instance)->SendCommand(
-        std::vector<uint8_t>(data, data + len));
+  void serviceDied() {
+    if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
+      ALOGE("Bluetooth remote service has died");
+    } else {
+      ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
+      return;
+    }
+    {
+      std::lock_guard<std::mutex> guard(mHasDiedMutex);
+      has_died_ = true;
+    }
+    mHci->close();
   }
-
-  static void SendAcl(void* instance, const uint8_t* data, size_t len) {
-    static_cast<Hal*>(instance)->SendAcl(
-        std::vector<uint8_t>(data, data + len));
-  }
-
-  static void SendSco(void* instance, const uint8_t* data, size_t len) {
-    static_cast<Hal*>(instance)->SendSco(
-        std::vector<uint8_t>(data, data + len));
-  }
-
-  static void SendIso(void* instance, const uint8_t* data, size_t len) {
-    static_cast<Hal*>(instance)->SendIso(
-        std::vector<uint8_t>(data, data + len));
+  BluetoothHci* mHci;
+  std::shared_ptr<IBluetoothHciCallbacks> mCb;
+  AIBinder_DeathRecipient* clientDeathRecipient_;
+  bool getHasDied() {
+    std::lock_guard<std::mutex> guard(mHasDiedMutex);
+    return has_died_;
   }
 
  private:
-  int getFdFromDevPath() {
-    int fd = open(mDevPath.c_str(), O_RDWR);
-    if (fd < 0) {
-      ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
-            strerror(errno));
-      return fd;
-    }
-    if (int ret = SetTerminalRaw(fd) < 0) {
-      ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
-            strerror(errno));
-    }
-    return fd;
-  }
-
-  void reset() {
-    // Send a reset command and wait until the command complete comes back.
-
-    std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
-
-    auto resetPromise = std::make_shared<std::promise<void>>();
-    auto resetFuture = resetPromise->get_future();
-
-    mH4 = std::make_shared<H4Protocol>(
-        mFd,
-        [](const std::vector<uint8_t>& raw_command) {
-          ALOGI("Discarding %d bytes with command type",
-                static_cast<int>(raw_command.size()));
-        },
-        [](const std::vector<uint8_t>& raw_acl) {
-          ALOGI("Discarding %d bytes with acl type",
-                static_cast<int>(raw_acl.size()));
-        },
-        [](const std::vector<uint8_t>& raw_sco) {
-          ALOGI("Discarding %d bytes with sco type",
-                static_cast<int>(raw_sco.size()));
-        },
-        [resetPromise](const std::vector<uint8_t>& raw_event) {
-          std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
-                                                 0x03, 0x0c, 0x00};
-          bool valid = raw_event.size() == 6 &&
-                       raw_event[0] == reset_complete[0] &&
-                       raw_event[1] == reset_complete[1] &&
-                       // Don't compare the number of packets field.
-                       raw_event[3] == reset_complete[3] &&
-                       raw_event[4] == reset_complete[4] &&
-                       raw_event[5] == reset_complete[5];
-          if (valid) {
-            resetPromise->set_value();
-          } else {
-            ALOGI("Discarding %d bytes with event type",
-                  static_cast<int>(raw_event.size()));
-          }
-        },
-        [](const std::vector<uint8_t>& raw_iso) {
-          ALOGI("Discarding %d bytes with iso type",
-                static_cast<int>(raw_iso.size()));
-        },
-        [this]() {
-          ALOGI("HCI socket device disconnected while waiting for reset");
-          mFdWatcher.StopWatchingFileDescriptors();
-        });
-    mFdWatcher.WatchFdForNonBlockingReads(mFd,
-                                          [this](int) { mH4->OnDataReady(); });
-
-    if (!send(PacketType::COMMAND, reset)) {
-      ALOGE("Error sending reset command");
-    }
-    auto status = resetFuture.wait_for(std::chrono::seconds(1));
-    mFdWatcher.StopWatchingFileDescriptors();
-    if (status == std::future_status::ready) {
-      ALOGI("HCI Reset successful");
-    } else {
-      ALOGE("HCI Reset Response not received in one second");
-    }
-
-    resetPromise.reset();
-  }
-
-  void Initialize(const struct hal_callbacks* callbacks) {
-    ALOGI(__func__);
-
-    HalState old_state = HalState::READY;
-    {
-      std::lock_guard<std::mutex> guard(mStateMutex);
-      if (mState != HalState::READY) {
-        old_state = mState;
-      } else {
-        mState = HalState::INITIALIZING;
-      }
-    }
-
-    if (old_state != HalState::READY) {
-      ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
-      Close();
-      callbacks->initialization_complete(callbacks->handle,
-                                         STATUS_ALREADY_INITIALIZED);
-      return;
-    }
-
-    mCallbacks = std::make_unique<struct hal_callbacks>(*callbacks);
-    management_.reset(new NetBluetoothMgmt);
-    mFd = management_->openHci();
-    if (mFd < 0) {
-      management_.reset();
-
-      ALOGI("Unable to open Linux interface, trying default path.");
-      mFd = getFdFromDevPath();
-      if (mFd < 0) {
-        mState = HalState::READY;
-        mCallbacks->initialization_complete(mCallbacks->handle,
-                                            STATUS_UNABLE_TO_OPEN_INTERFACE);
-        return;
-      }
-    }
-
-    // TODO: HCI Reset on emulators since the bluetooth controller
-    // cannot be powered on/off during the HAL setup; and the stack
-    // might received spurious packets/events during boottime.
-    // Proper solution would be to use bt-virtio or vsock to better
-    // control the link to rootcanal and the controller lifetime.
-    const std::string kBoardProperty = "ro.product.board";
-    const std::string kCuttlefishBoard = "cutf";
-    auto board_name = GetSystemProperty(kBoardProperty);
-    if (board_name.has_value() &&
-        (starts_with(board_name.value(), "cutf") ||
-         starts_with(board_name.value(), "goldfish"))) {
-      reset();
-    }
-
-    mH4 = std::make_shared<H4Protocol>(
-        mFd,
-        [](const std::vector<uint8_t>& /* raw_command */) {
-          LOG_ALWAYS_FATAL("Unexpected command!");
-        },
-        [this](const std::vector<uint8_t>& raw_acl) {
-          mCallbacks->acl_received(mCallbacks->handle, raw_acl.data(),
-                                   raw_acl.size());
-        },
-        [this](const std::vector<uint8_t>& raw_sco) {
-          mCallbacks->sco_received(mCallbacks->handle, raw_sco.data(),
-                                   raw_sco.size());
-        },
-        [this](const std::vector<uint8_t>& raw_event) {
-          mCallbacks->event_received(mCallbacks->handle, raw_event.data(),
-                                     raw_event.size());
-        },
-        [this](const std::vector<uint8_t>& raw_iso) {
-          mCallbacks->iso_received(mCallbacks->handle, raw_iso.data(),
-                                   raw_iso.size());
-        },
-        [this]() {
-          ALOGI("HCI socket device disconnected");
-          mFdWatcher.StopWatchingFileDescriptors();
-        });
-    mFdWatcher.WatchFdForNonBlockingReads(mFd,
-                                          [this](int) { mH4->OnDataReady(); });
-
-    {
-      std::lock_guard<std::mutex> guard(mStateMutex);
-      mState = HalState::ONE_CLIENT;
-    }
-
-    ALOGI("initialization complete");
-    mCallbacks->initialization_complete(mCallbacks->handle, STATUS_SUCCESS);
-  }
-
-  void Close() {
-    ALOGI(__func__);
-    {
-      std::lock_guard<std::mutex> guard(mStateMutex);
-      if (mState != HalState::ONE_CLIENT) {
-        LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
-                            "mState is INITIALIZING");
-        ALOGI("Already closed");
-        return;
-      }
-      mCallbacks.reset();
-      mState = HalState::CLOSING;
-    }
-
-    mFdWatcher.StopWatchingFileDescriptors();
-
-    if (management_) {
-      management_->closeHci();
-    } else {
-      ::close(mFd);
-    }
-
-    {
-      std::lock_guard<std::mutex> guard(mStateMutex);
-      mState = HalState::READY;
-      mH4 = nullptr;
-    }
-  }
-
-  void SendCommand(const std::vector<uint8_t>& data) {
-    send(PacketType::COMMAND, data);
-  }
-  void SendAcl(const std::vector<uint8_t>& data) {
-    send(PacketType::ACL_DATA, data);
-  }
-  void SendSco(const std::vector<uint8_t>& data) {
-    send(PacketType::SCO_DATA, data);
-  }
-  void SendIso(const std::vector<uint8_t>& data) {
-    send(PacketType::ISO_DATA, data);
-  }
-
-  bool send(PacketType type, const std::vector<uint8_t>& v) {
-    if (v.empty()) {
-      ALOGE("Packet is empty, no data was found to be sent");
-      return false;
-    }
-
-    std::lock_guard<std::mutex> guard(mStateMutex);
-    if (mH4 == nullptr) {
-      ALOGE("Illegal State");
-      return false;
-    }
-
-    mH4->Send(type, v);
-    return true;
-  }
-
-  std::unique_ptr<struct hal_callbacks> mCallbacks;
-  std::string mDevPath;
-  int mFd{-1};
-  ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
-  std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;
-  std::unique_ptr<NetBluetoothMgmt> management_{};
-
-  // Don't close twice or open before close is complete
-  std::mutex mStateMutex;
-  enum class HalState {
-    READY,
-    INITIALIZING,
-    ONE_CLIENT,
-    CLOSING,
-  } mState{HalState::READY};
+  std::mutex mHasDiedMutex;
+  bool has_died_{false};
 };
 
+void OnDeath(void* cookie) {
+  auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
+  death_recipient->serviceDied();
+}
+
+BluetoothHci::BluetoothHci(const std::string& dev_path) {
+  char property_bytes[PROPERTY_VALUE_MAX];
+  property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
+  mDevPath = std::string(property_bytes);
+  mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
+}
+
+int BluetoothHci::getFdFromDevPath() {
+  int fd = open(mDevPath.c_str(), O_RDWR);
+  if (fd < 0) {
+    ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
+          strerror(errno));
+    return fd;
+  }
+  if (int ret = SetTerminalRaw(fd) < 0) {
+    ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
+          strerror(errno));
+  }
+  return fd;
+}
+
+void BluetoothHci::reset() {
+  // Send a reset command and wait until the command complete comes back.
+
+  std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
+
+  auto resetPromise = std::make_shared<std::promise<void>>();
+  auto resetFuture = resetPromise->get_future();
+
+  mH4 = std::make_shared<H4Protocol>(
+      mFd,
+      [](const std::vector<uint8_t>& raw_command) {
+        ALOGI("Discarding %d bytes with command type",
+              static_cast<int>(raw_command.size()));
+      },
+      [](const std::vector<uint8_t>& raw_acl) {
+        ALOGI("Discarding %d bytes with acl type",
+              static_cast<int>(raw_acl.size()));
+      },
+      [](const std::vector<uint8_t>& raw_sco) {
+        ALOGI("Discarding %d bytes with sco type",
+              static_cast<int>(raw_sco.size()));
+      },
+      [resetPromise](const std::vector<uint8_t>& raw_event) {
+        std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
+                                               0x03, 0x0c, 0x00};
+        bool valid = raw_event.size() == 6 &&
+                     raw_event[0] == reset_complete[0] &&
+                     raw_event[1] == reset_complete[1] &&
+                     // Don't compare the number of packets field.
+                     raw_event[3] == reset_complete[3] &&
+                     raw_event[4] == reset_complete[4] &&
+                     raw_event[5] == reset_complete[5];
+        if (valid) {
+          resetPromise->set_value();
+        } else {
+          ALOGI("Discarding %d bytes with event type",
+                static_cast<int>(raw_event.size()));
+        }
+      },
+      [](const std::vector<uint8_t>& raw_iso) {
+        ALOGI("Discarding %d bytes with iso type",
+              static_cast<int>(raw_iso.size()));
+      },
+      [this]() {
+        ALOGI("HCI socket device disconnected while waiting for reset");
+        mFdWatcher.StopWatchingFileDescriptors();
+      });
+  mFdWatcher.WatchFdForNonBlockingReads(mFd,
+                                        [this](int) { mH4->OnDataReady(); });
+
+  ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
+  if (!result.isOk()) {
+    ALOGE("Error sending reset command");
+  }
+  auto status = resetFuture.wait_for(std::chrono::seconds(1));
+  mFdWatcher.StopWatchingFileDescriptors();
+  if (status == std::future_status::ready) {
+    ALOGI("HCI Reset successful");
+  } else {
+    ALOGE("HCI Reset Response not received in one second");
+  }
+
+  resetPromise.reset();
+}
+
+ndk::ScopedAStatus BluetoothHci::initialize(
+    const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
+  ALOGI(__func__);
+
+  if (cb == nullptr) {
+    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+    return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
+  }
+
+  HalState old_state = HalState::READY;
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    if (mState != HalState::READY) {
+      old_state = mState;
+    } else {
+      mState = HalState::INITIALIZING;
+    }
+  }
+
+  if (old_state != HalState::READY) {
+    ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
+    close();
+    cb->initializationComplete(Status::ALREADY_INITIALIZED);
+    return ndk::ScopedAStatus::ok();
+  }
+
+  mCb = cb;
+  management_.reset(new NetBluetoothMgmt);
+  mFd = management_->openHci();
+  if (mFd < 0) {
+    management_.reset();
+
+    ALOGI("Unable to open Linux interface, trying default path.");
+    mFd = getFdFromDevPath();
+    if (mFd < 0) {
+      mState = HalState::READY;
+      cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
+      return ndk::ScopedAStatus::ok();
+    }
+  }
+
+  mDeathRecipient->LinkToDeath(mCb);
+
+  // TODO: HCI Reset on emulators since the bluetooth controller
+  // cannot be powered on/off during the HAL setup; and the stack
+  // might received spurious packets/events during boottime.
+  // Proper solution would be to use bt-virtio or vsock to better
+  // control the link to rootcanal and the controller lifetime.
+  const std::string kBoardProperty = "ro.product.board";
+  const std::string kCuttlefishBoard = "cutf";
+  auto board_name = GetSystemProperty(kBoardProperty);
+  if (board_name.has_value() && (
+        starts_with(board_name.value(), "cutf") ||
+        starts_with(board_name.value(), "goldfish"))) {
+    reset();
+  }
+
+  mH4 = std::make_shared<H4Protocol>(
+      mFd,
+      [](const std::vector<uint8_t>& /* raw_command */) {
+        LOG_ALWAYS_FATAL("Unexpected command!");
+      },
+      [this](const std::vector<uint8_t>& raw_acl) {
+        mCb->aclDataReceived(raw_acl);
+      },
+      [this](const std::vector<uint8_t>& raw_sco) {
+        mCb->scoDataReceived(raw_sco);
+      },
+      [this](const std::vector<uint8_t>& raw_event) {
+        mCb->hciEventReceived(raw_event);
+      },
+      [this](const std::vector<uint8_t>& raw_iso) {
+        mCb->isoDataReceived(raw_iso);
+      },
+      [this]() {
+        ALOGI("HCI socket device disconnected");
+        mFdWatcher.StopWatchingFileDescriptors();
+      });
+  mFdWatcher.WatchFdForNonBlockingReads(mFd,
+                                        [this](int) { mH4->OnDataReady(); });
+
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    mState = HalState::ONE_CLIENT;
+  }
+  ALOGI("initialization complete");
+  auto status = mCb->initializationComplete(Status::SUCCESS);
+  if (!status.isOk()) {
+    if (!mDeathRecipient->getHasDied()) {
+      ALOGE("Error sending init callback, but no death notification");
+    }
+    close();
+    return ndk::ScopedAStatus::fromServiceSpecificError(
+        STATUS_FAILED_TRANSACTION);
+  }
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::close() {
+  ALOGI(__func__);
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    if (mState != HalState::ONE_CLIENT) {
+      LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
+                          "mState is INITIALIZING");
+      ALOGI("Already closed");
+      return ndk::ScopedAStatus::ok();
+    }
+    mState = HalState::CLOSING;
+  }
+
+  mFdWatcher.StopWatchingFileDescriptors();
+
+  if (management_) {
+    management_->closeHci();
+  } else {
+    ::close(mFd);
+  }
+
+  {
+    std::lock_guard<std::mutex> guard(mStateMutex);
+    mState = HalState::READY;
+    mH4 = nullptr;
+  }
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::sendHciCommand(
+    const std::vector<uint8_t>& packet) {
+  return send(PacketType::COMMAND, packet);
+}
+
+ndk::ScopedAStatus BluetoothHci::sendAclData(
+    const std::vector<uint8_t>& packet) {
+  return send(PacketType::ACL_DATA, packet);
+}
+
+ndk::ScopedAStatus BluetoothHci::sendScoData(
+    const std::vector<uint8_t>& packet) {
+  return send(PacketType::SCO_DATA, packet);
+}
+
+ndk::ScopedAStatus BluetoothHci::sendIsoData(
+    const std::vector<uint8_t>& packet) {
+  return send(PacketType::ISO_DATA, packet);
+}
+
+ndk::ScopedAStatus BluetoothHci::send(PacketType type,
+    const std::vector<uint8_t>& v) {
+  if (v.empty()) {
+    ALOGE("Packet is empty, no data was found to be sent");
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  std::lock_guard<std::mutex> guard(mStateMutex);
+  if (mH4 == nullptr) {
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+  }
+
+  mH4->Send(type, v);
+  return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::bluetooth::impl
-
-extern "C" {
-
-using namespace aidl::android::hardware::bluetooth::impl;
-
-struct hal_interface hal_new() {
-  return (struct hal_interface){
-      .handle = new Hal(),
-      .initialize = &Hal::Initialize,
-      .close = &Hal::Close,
-      .send_command = &Hal::SendCommand,
-      .send_acl = &Hal::SendAcl,
-      .send_sco = &Hal::SendSco,
-      .send_iso = &Hal::SendIso,
-  };
-}
-}
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
new file mode 100644
index 0000000..477cc5c
--- /dev/null
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
+#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
+
+#include <future>
+#include <string>
+
+#include "async_fd_watcher.h"
+#include "h4_protocol.h"
+#include "net_bluetooth_mgmt.h"
+
+namespace aidl::android::hardware::bluetooth::impl {
+
+class BluetoothDeathRecipient;
+
+// This Bluetooth HAL implementation connects with a serial port at dev_path_.
+class BluetoothHci : public BnBluetoothHci {
+ public:
+  BluetoothHci(const std::string& dev_path = "/dev/hvc5");
+
+  ndk::ScopedAStatus initialize(
+      const std::shared_ptr<IBluetoothHciCallbacks>& cb) override;
+
+  ndk::ScopedAStatus sendHciCommand(
+      const std::vector<uint8_t>& packet) override;
+
+  ndk::ScopedAStatus sendAclData(const std::vector<uint8_t>& packet) override;
+
+  ndk::ScopedAStatus sendScoData(const std::vector<uint8_t>& packet) override;
+
+  ndk::ScopedAStatus sendIsoData(const std::vector<uint8_t>& packet) override;
+
+  ndk::ScopedAStatus close() override;
+
+  static void OnPacketReady();
+
+  static BluetoothHci* get();
+
+ private:
+  int mFd{-1};
+  std::shared_ptr<IBluetoothHciCallbacks> mCb = nullptr;
+
+  std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;
+
+  std::shared_ptr<BluetoothDeathRecipient> mDeathRecipient;
+
+  std::string mDevPath;
+
+  ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
+
+  int getFdFromDevPath();
+  [[nodiscard]] ndk::ScopedAStatus send(
+      ::android::hardware::bluetooth::hci::PacketType type,
+      const std::vector<uint8_t>& packet);
+  std::unique_ptr<NetBluetoothMgmt> management_{};
+
+  // Send a reset command and discard all packets until a reset is received.
+  void reset();
+
+  // Don't close twice or open before close is complete
+  std::mutex mStateMutex;
+  enum class HalState {
+    READY,
+    INITIALIZING,
+    ONE_CLIENT,
+    CLOSING,
+  } mState{HalState::READY};
+};
+
+}  // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/main.rs b/bluetooth/aidl/default/main.rs
deleted file mode 100644
index b30162a..0000000
--- a/bluetooth/aidl/default/main.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2024, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use android_hardware_bluetooth::aidl::android::hardware::bluetooth::IBluetoothHci::{
-    self,
-    IBluetoothHci as _
-};
-use android_hardware_bluetooth::binder;
-use bluetooth_offload_hal::{ HciHalProxy, CInterface };
-use bluetooth_offload_leaudio_hci::LeAudioModuleBuilder;
-use log;
-use std::panic;
-
-fn new_hal() -> CInterface {
-    extern "C" { fn hal_new() -> CInterface; }
-    unsafe { hal_new() }
-}
-
-fn main() {
-    logger::init(
-        logger::Config::default()
-            .with_max_level(log::LevelFilter::Debug)
-            .with_tag_on_device("android.hardware.bluetooth"),
-    );
-
-    panic::set_hook(Box::new(|panic_info| {
-        log::error!("{}", panic_info);
-    }));
-
-    log::info!("Bluetooth HAL starting up");
-
-    binder::ProcessState::set_thread_pool_max_thread_count(0);
-    binder::ProcessState::start_thread_pool();
-
-    binder::add_service(
-        &format!("{}/default", IBluetoothHci::BpBluetoothHci::get_descriptor()),
-        IBluetoothHci::BnBluetoothHci::new_binder(
-            HciHalProxy::new(
-                vec![ Box::new(LeAudioModuleBuilder {}) ],
-                new_hal()
-            ),
-            binder::BinderFeatures::default(),
-        ).as_binder()
-    ).expect("Failed to register service");
-
-    binder::ProcessState::join_thread_pool();
-}
diff --git a/bluetooth/aidl/default/service.cpp b/bluetooth/aidl/default/service.cpp
new file mode 100644
index 0000000..ef4b884
--- /dev/null
+++ b/bluetooth/aidl/default/service.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "aidl.android.hardware.bluetooth.service.default"
+
+#include <aidl/android/hardware/bluetooth/IBluetoothHci.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "BluetoothHci.h"
+
+using ::aidl::android::hardware::bluetooth::impl::BluetoothHci;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+
+int main(int /* argc */, char** /* argv */) {
+  ALOGI("Bluetooth HAL starting");
+  if (!ABinderProcess_setThreadPoolMaxThreadCount(0)) {
+    ALOGI("failed to set thread pool max thread count");
+    return 1;
+  }
+
+  std::shared_ptr<BluetoothHci> service =
+      ndk::SharedRefBase::make<BluetoothHci>();
+  std::string instance = std::string() + BluetoothHci::descriptor + "/default";
+  auto result =
+      AServiceManager_addService(service->asBinder().get(), instance.c_str());
+  if (result == STATUS_OK) {
+    ABinderProcess_joinThreadPool();
+  } else {
+    ALOGE("Could not register as a service!");
+  }
+  return 0;
+}
diff --git a/bluetooth/aidl/default/test/fuzzer.cpp b/bluetooth/aidl/default/test/fuzzer.cpp
new file mode 100644
index 0000000..e7a1eef
--- /dev/null
+++ b/bluetooth/aidl/default/test/fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "BluetoothHci.h"
+
+using aidl::android::hardware::bluetooth::impl::BluetoothHci;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  auto service = SharedRefBase::make<BluetoothHci>();
+
+  fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+
+  return 0;
+}