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;
+}