Loading system/gd/hal/hci_hal.h +27 −9 Original line number Diff line number Diff line Loading @@ -25,17 +25,16 @@ using HciPacket = std::vector<uint8_t>; enum class Status : int32_t { SUCCESS, TRANSPORT_ERROR, INITIALIZATION_ERROR, UNKNOWN }; // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHciCallbacks.hal in Android // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHciCallbacks.hal in Android, but moved initializationComplete // callback to BluetoothInitializationCompleteCallback // The interface from the Bluetooth Controller to the stack class BluetoothHciHalCallbacks { public: virtual ~BluetoothHciHalCallbacks() = default; // Invoked when the Bluetooth controller initialization has been completed virtual void initializationComplete(Status status) = 0; // This function is invoked when an HCI event is received from the Bluetooth controller to be forwarded to the // Bluetooth stack // This function is invoked when an HCI event is received from the // Bluetooth controller to be forwarded to the Bluetooth stack // @param event is the HCI event to be sent to the Bluetooth stack virtual void hciEventReceived(HciPacket event) = 0; Loading @@ -48,6 +47,15 @@ class BluetoothHciHalCallbacks { virtual void scoDataReceived(HciPacket data) = 0; }; // Callback for BluetoothHciHal::initialize() class BluetoothInitializationCompleteCallback { public: virtual ~BluetoothInitializationCompleteCallback() = default; // Invoked when the Bluetooth controller initialization has been completed virtual void initializationComplete(Status status) = 0; }; // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal in Android // The Host Controller Interface (HCI) is the layer defined by the Bluetooth // specification between the software that runs on the host and the Bluetooth Loading @@ -65,15 +73,25 @@ class BluetoothHciHal { // required to communicate with the Bluetooth hardware in the // device. // // The |oninitializationComplete| callback must be invoked in response // The |InitializationCompleteCallback| callback must be invoked in response // to this function to indicate success before any other function // (sendHciCommand, sendAclData, * sendScoData) is invoked on this // interface. // // @param callback implements IBluetoothHciCallbacks which will // @param callback implements BluetoothInitializationCompleteCallback which will // receive callbacks when incoming HCI initialization is complete virtual void initialize(BluetoothInitializationCompleteCallback* callback) = 0; // Register the callback for incoming packets. All incoming packets are dropped before // this callback is registered. Callback can only be registered once, but will be reset // after close(). // // Call this function before initialize() to guarantee all incoming packets are received. // // @param callback implements BluetoothHciHalCallbacks which will // receive callbacks when incoming HCI packets are received // from the controller to be sent to the host. virtual void initialize(BluetoothHciHalCallbacks* callback) = 0; virtual void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) = 0; // Send an HCI command (as specified in the Bluetooth Specification // V4.2, Vol 2, Part 5, Section 5.4.1) to the Bluetooth controller. Loading system/gd/hal/hci_hal_android_hidl.cc +32 −9 Original line number Diff line number Diff line Loading @@ -47,38 +47,55 @@ android::sp<BluetoothHciDeathRecipient> bluetooth_hci_death_recipient_ = new Blu class HciHalBluetoothHciCallbacks : public IBluetoothHciCallbacks { public: HciHalBluetoothHciCallbacks(BluetoothHciHalCallbacks* callback) : callback_(callback) {} HciHalBluetoothHciCallbacks(BluetoothInitializationCompleteCallback* initialization_callback) : initialization_callback_(initialization_callback) {} void SetCallback(BluetoothHciHalCallbacks* callback) { ASSERT(callback_ == nullptr && callback != nullptr); callback_ = callback; } void ResetCallback() { callback_ = nullptr; } Return<void> initializationComplete(HidlStatus status) { ASSERT(status == HidlStatus::SUCCESS); callback_->initializationComplete(Status::SUCCESS); initialization_callback_->initializationComplete(Status::SUCCESS); return Void(); } Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) { if (callback_ != nullptr) { callback_->hciEventReceived(std::vector<uint8_t>(event.begin(), event.end())); } return Void(); } Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) { if (callback_ != nullptr) { callback_->aclDataReceived(std::vector<uint8_t>(data.begin(), data.end())); } return Void(); } Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) { if (callback_ != nullptr) { callback_->scoDataReceived(std::vector<uint8_t>(data.begin(), data.end())); } return Void(); } private: BluetoothHciHalCallbacks* callback_; BluetoothInitializationCompleteCallback* initialization_callback_ = nullptr; BluetoothHciHalCallbacks* callback_ = nullptr; }; } // namespace class BluetoothHciHalHidl : public BluetoothHciHal { public: void initialize(BluetoothHciHalCallbacks* callback) override { void initialize(BluetoothInitializationCompleteCallback* callback) override { bt_hci_ = IBluetoothHci::getService(); ASSERT(bt_hci_ != nullptr); auto death_link = bt_hci_->linkToDeath(bluetooth_hci_death_recipient_, 0); Loading @@ -86,11 +103,15 @@ class BluetoothHciHalHidl : public BluetoothHciHal { // Block allows allocation of a variable that might be bypassed by goto. { android::sp<IBluetoothHciCallbacks> callbacks = new HciHalBluetoothHciCallbacks(callback); bt_hci_->initialize(callbacks); callbacks_ = new HciHalBluetoothHciCallbacks(callback); bt_hci_->initialize(callbacks_); } } void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) override { callbacks_->SetCallback(callback); } void sendHciCommand(HciPacket command) override { bt_hci_->sendHciCommand(command); } Loading @@ -110,10 +131,12 @@ class BluetoothHciHalHidl : public BluetoothHciHal { LOG_ERROR("Error unlinking death recipient from the Bluetooth HAL"); } bt_hci_->close(); callbacks_->ResetCallback(); bt_hci_ = nullptr; } private: android::sp<HciHalBluetoothHciCallbacks> callbacks_; android::sp<IBluetoothHci> bt_hci_; }; Loading system/gd/hal/hci_hal_android_hidl_test.cc +19 −9 Original line number Diff line number Diff line /* * Copyright 2019 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 "hal/hci_hal.h" #include <chrono> Loading @@ -11,18 +27,12 @@ namespace { std::promise<void>* g_promise; class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks { class TestBluetoothInitializationCompleteCallback : public BluetoothInitializationCompleteCallback { public: void initializationComplete(Status status) override { EXPECT_EQ(status, Status::SUCCESS); g_promise->set_value(); } void hciEventReceived(HciPacket) override {} void aclDataReceived(HciPacket) override {} void scoDataReceived(HciPacket) override {} }; class HciHalHidlTest : public ::testing::Test { Loading @@ -30,7 +40,7 @@ class HciHalHidlTest : public ::testing::Test { void SetUp() override { g_promise = new std::promise<void>; hal_ = GetBluetoothHciHal(); hal_->initialize(&callbacks_); hal_->initialize(&init_callback_); } void TearDown() override { Loading @@ -40,7 +50,7 @@ class HciHalHidlTest : public ::testing::Test { } BluetoothHciHal* hal_ = nullptr; TestBluetoothHciHalCallbacks callbacks_; TestBluetoothInitializationCompleteCallback init_callback_; }; TEST_F(HciHalHidlTest, init_and_close) { Loading system/gd/hal/hci_hal_host_rootcanal.cc +31 −23 Original line number Diff line number Diff line Loading @@ -19,20 +19,17 @@ #include <fcntl.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/ip.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <mutex> #include <queue> #include <string> #include "os/log.h" #include "os/reactor.h" #include "os/thread.h" namespace { constexpr int INVALID_FD = -1; constexpr uint8_t kH4Command = 0x01; constexpr uint8_t kH4Acl = 0x02; constexpr uint8_t kH4Sco = 0x03; Loading @@ -48,14 +45,14 @@ int ConnectToRootCanal(const std::string& server, int port) { int socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 1) { LOG_ERROR("can't create socket: %s", strerror(errno)); return -1; return INVALID_FD; } struct hostent* host; host = gethostbyname(server.c_str()); if (host == nullptr) { LOG_ERROR("can't get server name"); return -1; return INVALID_FD; } struct sockaddr_in serv_addr; Loading @@ -67,14 +64,14 @@ int ConnectToRootCanal(const std::string& server, int port) { int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); if (result < 0) { LOG_ERROR("can't connect: %s", strerror(errno)); return -1; return INVALID_FD; } int flags = fcntl(socket_fd, F_GETFL, NULL); int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK); if (ret == -1) { LOG_ERROR("can't control socket fd: %s", strerror(errno)); return -1; return INVALID_FD; } return socket_fd; } Loading @@ -85,20 +82,26 @@ namespace hal { class BluetoothHciHalHostRootcanal : public BluetoothHciHal { public: void initialize(BluetoothHciHalCallbacks* callback) override { void initialize(BluetoothInitializationCompleteCallback* callback) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ == nullptr && callback != nullptr); ASSERT(sock_fd_ == INVALID_FD && callback != nullptr); sock_fd_ = ConnectToRootCanal(config_->GetServerAddress(), config_->GetPort()); ASSERT(sock_fd_ != INVALID_FD); reactable_ = hci_incoming_thread_.GetReactor()->Register(sock_fd_, [this]() { this->incoming_packet_received(); }, nullptr); callback_ = callback; callback->initializationComplete(Status::SUCCESS); LOG_INFO("Rootcanal HAL opened successfully"); } void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr); incoming_packet_callback_ = callback; } void sendHciCommand(HciPacket command) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); ASSERT(sock_fd_ != INVALID_FD); std::vector<uint8_t> packet = std::move(command); packet.insert(packet.cbegin(), kH4Command); write_to_rootcanal_fd(packet); Loading @@ -106,7 +109,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { void sendAclData(HciPacket data) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); ASSERT(sock_fd_ != INVALID_FD); std::vector<uint8_t> packet = std::move(data); packet.insert(packet.cbegin(), kH4Acl); write_to_rootcanal_fd(packet); Loading @@ -114,7 +117,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { void sendScoData(HciPacket data) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); ASSERT(sock_fd_ != INVALID_FD); std::vector<uint8_t> packet = std::move(data); packet.insert(packet.cbegin(), kH4Sco); write_to_rootcanal_fd(packet); Loading @@ -122,19 +125,22 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { void close() override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); if (reactable_ != nullptr) { hci_incoming_thread_.GetReactor()->Unregister(reactable_); ASSERT(sock_fd_ != INVALID_FD); } reactable_ = nullptr; callback_ = nullptr; incoming_packet_callback_ = nullptr; ::close(sock_fd_); sock_fd_ = INVALID_FD; LOG_INFO("Rootcanal HAL is closed"); } private: std::mutex mutex_; HciHalHostRootcanalConfig* config_ = HciHalHostRootcanalConfig::Get(); BluetoothHciHalCallbacks* callback_ = nullptr; int sock_fd_ = 0; BluetoothHciHalCallbacks* incoming_packet_callback_ = nullptr; int sock_fd_ = INVALID_FD; bluetooth::os::Thread hci_incoming_thread_ = bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL); bluetooth::os::Reactor::Reactable* reactable_ = nullptr; Loading Loading @@ -163,6 +169,8 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { } void incoming_packet_received() { ASSERT(incoming_packet_callback_ != nullptr); uint8_t buf[kBufSize] = {}; ssize_t received_size; Loading @@ -188,7 +196,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size); callback_->hciEventReceived(receivedHciPacket); incoming_packet_callback_->hciEventReceived(receivedHciPacket); } if (buf[0] == kH4Acl) { Loading @@ -204,7 +212,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size); callback_->aclDataReceived(receivedHciPacket); incoming_packet_callback_->aclDataReceived(receivedHciPacket); } if (buf[0] == kH4Sco) { Loading @@ -217,7 +225,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size); callback_->scoDataReceived(receivedHciPacket); incoming_packet_callback_->scoDataReceived(receivedHciPacket); } memset(buf, 0, kBufSize); } Loading system/gd/hal/hci_hal_host_rootcanal_test.cc +7 −2 Original line number Diff line number Diff line Loading @@ -50,12 +50,15 @@ using H4Packet = std::vector<uint8_t>; std::queue<std::pair<uint8_t, HciPacket>> incoming_packets_queue_; class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks { class TestBluetoothInitializationCompleteCallback : public BluetoothInitializationCompleteCallback { public: void initializationComplete(Status status) override { EXPECT_EQ(status, Status::SUCCESS); } }; class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks { public: void hciEventReceived(HciPacket packet) override { incoming_packets_queue_.emplace(kH4Event, packet); } Loading Loading @@ -139,7 +142,8 @@ class HciHalRootcanalTest : public ::testing::Test { HciHalHostRootcanalConfig::Get()->SetPort(kTestPort); fake_server_ = new FakeRootcanalDesktopHciServer; hal_ = GetBluetoothHciHal(); hal_->initialize(&callbacks_); hal_->initialize(&init_callback_); hal_->registerIncomingPacketCallback(&callbacks_); fake_server_socket_ = fake_server_->Accept(); // accept() after client is connected to avoid blocking std::queue<std::pair<uint8_t, HciPacket>> empty; std::swap(incoming_packets_queue_, empty); Loading @@ -159,6 +163,7 @@ class HciHalRootcanalTest : public ::testing::Test { FakeRootcanalDesktopHciServer* fake_server_ = nullptr; BluetoothHciHal* hal_ = nullptr; TestBluetoothInitializationCompleteCallback init_callback_; TestBluetoothHciHalCallbacks callbacks_; int fake_server_socket_ = -1; }; Loading Loading
system/gd/hal/hci_hal.h +27 −9 Original line number Diff line number Diff line Loading @@ -25,17 +25,16 @@ using HciPacket = std::vector<uint8_t>; enum class Status : int32_t { SUCCESS, TRANSPORT_ERROR, INITIALIZATION_ERROR, UNKNOWN }; // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHciCallbacks.hal in Android // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHciCallbacks.hal in Android, but moved initializationComplete // callback to BluetoothInitializationCompleteCallback // The interface from the Bluetooth Controller to the stack class BluetoothHciHalCallbacks { public: virtual ~BluetoothHciHalCallbacks() = default; // Invoked when the Bluetooth controller initialization has been completed virtual void initializationComplete(Status status) = 0; // This function is invoked when an HCI event is received from the Bluetooth controller to be forwarded to the // Bluetooth stack // This function is invoked when an HCI event is received from the // Bluetooth controller to be forwarded to the Bluetooth stack // @param event is the HCI event to be sent to the Bluetooth stack virtual void hciEventReceived(HciPacket event) = 0; Loading @@ -48,6 +47,15 @@ class BluetoothHciHalCallbacks { virtual void scoDataReceived(HciPacket data) = 0; }; // Callback for BluetoothHciHal::initialize() class BluetoothInitializationCompleteCallback { public: virtual ~BluetoothInitializationCompleteCallback() = default; // Invoked when the Bluetooth controller initialization has been completed virtual void initializationComplete(Status status) = 0; }; // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal in Android // The Host Controller Interface (HCI) is the layer defined by the Bluetooth // specification between the software that runs on the host and the Bluetooth Loading @@ -65,15 +73,25 @@ class BluetoothHciHal { // required to communicate with the Bluetooth hardware in the // device. // // The |oninitializationComplete| callback must be invoked in response // The |InitializationCompleteCallback| callback must be invoked in response // to this function to indicate success before any other function // (sendHciCommand, sendAclData, * sendScoData) is invoked on this // interface. // // @param callback implements IBluetoothHciCallbacks which will // @param callback implements BluetoothInitializationCompleteCallback which will // receive callbacks when incoming HCI initialization is complete virtual void initialize(BluetoothInitializationCompleteCallback* callback) = 0; // Register the callback for incoming packets. All incoming packets are dropped before // this callback is registered. Callback can only be registered once, but will be reset // after close(). // // Call this function before initialize() to guarantee all incoming packets are received. // // @param callback implements BluetoothHciHalCallbacks which will // receive callbacks when incoming HCI packets are received // from the controller to be sent to the host. virtual void initialize(BluetoothHciHalCallbacks* callback) = 0; virtual void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) = 0; // Send an HCI command (as specified in the Bluetooth Specification // V4.2, Vol 2, Part 5, Section 5.4.1) to the Bluetooth controller. Loading
system/gd/hal/hci_hal_android_hidl.cc +32 −9 Original line number Diff line number Diff line Loading @@ -47,38 +47,55 @@ android::sp<BluetoothHciDeathRecipient> bluetooth_hci_death_recipient_ = new Blu class HciHalBluetoothHciCallbacks : public IBluetoothHciCallbacks { public: HciHalBluetoothHciCallbacks(BluetoothHciHalCallbacks* callback) : callback_(callback) {} HciHalBluetoothHciCallbacks(BluetoothInitializationCompleteCallback* initialization_callback) : initialization_callback_(initialization_callback) {} void SetCallback(BluetoothHciHalCallbacks* callback) { ASSERT(callback_ == nullptr && callback != nullptr); callback_ = callback; } void ResetCallback() { callback_ = nullptr; } Return<void> initializationComplete(HidlStatus status) { ASSERT(status == HidlStatus::SUCCESS); callback_->initializationComplete(Status::SUCCESS); initialization_callback_->initializationComplete(Status::SUCCESS); return Void(); } Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) { if (callback_ != nullptr) { callback_->hciEventReceived(std::vector<uint8_t>(event.begin(), event.end())); } return Void(); } Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) { if (callback_ != nullptr) { callback_->aclDataReceived(std::vector<uint8_t>(data.begin(), data.end())); } return Void(); } Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) { if (callback_ != nullptr) { callback_->scoDataReceived(std::vector<uint8_t>(data.begin(), data.end())); } return Void(); } private: BluetoothHciHalCallbacks* callback_; BluetoothInitializationCompleteCallback* initialization_callback_ = nullptr; BluetoothHciHalCallbacks* callback_ = nullptr; }; } // namespace class BluetoothHciHalHidl : public BluetoothHciHal { public: void initialize(BluetoothHciHalCallbacks* callback) override { void initialize(BluetoothInitializationCompleteCallback* callback) override { bt_hci_ = IBluetoothHci::getService(); ASSERT(bt_hci_ != nullptr); auto death_link = bt_hci_->linkToDeath(bluetooth_hci_death_recipient_, 0); Loading @@ -86,11 +103,15 @@ class BluetoothHciHalHidl : public BluetoothHciHal { // Block allows allocation of a variable that might be bypassed by goto. { android::sp<IBluetoothHciCallbacks> callbacks = new HciHalBluetoothHciCallbacks(callback); bt_hci_->initialize(callbacks); callbacks_ = new HciHalBluetoothHciCallbacks(callback); bt_hci_->initialize(callbacks_); } } void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) override { callbacks_->SetCallback(callback); } void sendHciCommand(HciPacket command) override { bt_hci_->sendHciCommand(command); } Loading @@ -110,10 +131,12 @@ class BluetoothHciHalHidl : public BluetoothHciHal { LOG_ERROR("Error unlinking death recipient from the Bluetooth HAL"); } bt_hci_->close(); callbacks_->ResetCallback(); bt_hci_ = nullptr; } private: android::sp<HciHalBluetoothHciCallbacks> callbacks_; android::sp<IBluetoothHci> bt_hci_; }; Loading
system/gd/hal/hci_hal_android_hidl_test.cc +19 −9 Original line number Diff line number Diff line /* * Copyright 2019 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 "hal/hci_hal.h" #include <chrono> Loading @@ -11,18 +27,12 @@ namespace { std::promise<void>* g_promise; class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks { class TestBluetoothInitializationCompleteCallback : public BluetoothInitializationCompleteCallback { public: void initializationComplete(Status status) override { EXPECT_EQ(status, Status::SUCCESS); g_promise->set_value(); } void hciEventReceived(HciPacket) override {} void aclDataReceived(HciPacket) override {} void scoDataReceived(HciPacket) override {} }; class HciHalHidlTest : public ::testing::Test { Loading @@ -30,7 +40,7 @@ class HciHalHidlTest : public ::testing::Test { void SetUp() override { g_promise = new std::promise<void>; hal_ = GetBluetoothHciHal(); hal_->initialize(&callbacks_); hal_->initialize(&init_callback_); } void TearDown() override { Loading @@ -40,7 +50,7 @@ class HciHalHidlTest : public ::testing::Test { } BluetoothHciHal* hal_ = nullptr; TestBluetoothHciHalCallbacks callbacks_; TestBluetoothInitializationCompleteCallback init_callback_; }; TEST_F(HciHalHidlTest, init_and_close) { Loading
system/gd/hal/hci_hal_host_rootcanal.cc +31 −23 Original line number Diff line number Diff line Loading @@ -19,20 +19,17 @@ #include <fcntl.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/ip.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <mutex> #include <queue> #include <string> #include "os/log.h" #include "os/reactor.h" #include "os/thread.h" namespace { constexpr int INVALID_FD = -1; constexpr uint8_t kH4Command = 0x01; constexpr uint8_t kH4Acl = 0x02; constexpr uint8_t kH4Sco = 0x03; Loading @@ -48,14 +45,14 @@ int ConnectToRootCanal(const std::string& server, int port) { int socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 1) { LOG_ERROR("can't create socket: %s", strerror(errno)); return -1; return INVALID_FD; } struct hostent* host; host = gethostbyname(server.c_str()); if (host == nullptr) { LOG_ERROR("can't get server name"); return -1; return INVALID_FD; } struct sockaddr_in serv_addr; Loading @@ -67,14 +64,14 @@ int ConnectToRootCanal(const std::string& server, int port) { int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); if (result < 0) { LOG_ERROR("can't connect: %s", strerror(errno)); return -1; return INVALID_FD; } int flags = fcntl(socket_fd, F_GETFL, NULL); int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK); if (ret == -1) { LOG_ERROR("can't control socket fd: %s", strerror(errno)); return -1; return INVALID_FD; } return socket_fd; } Loading @@ -85,20 +82,26 @@ namespace hal { class BluetoothHciHalHostRootcanal : public BluetoothHciHal { public: void initialize(BluetoothHciHalCallbacks* callback) override { void initialize(BluetoothInitializationCompleteCallback* callback) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ == nullptr && callback != nullptr); ASSERT(sock_fd_ == INVALID_FD && callback != nullptr); sock_fd_ = ConnectToRootCanal(config_->GetServerAddress(), config_->GetPort()); ASSERT(sock_fd_ != INVALID_FD); reactable_ = hci_incoming_thread_.GetReactor()->Register(sock_fd_, [this]() { this->incoming_packet_received(); }, nullptr); callback_ = callback; callback->initializationComplete(Status::SUCCESS); LOG_INFO("Rootcanal HAL opened successfully"); } void registerIncomingPacketCallback(BluetoothHciHalCallbacks* callback) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr); incoming_packet_callback_ = callback; } void sendHciCommand(HciPacket command) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); ASSERT(sock_fd_ != INVALID_FD); std::vector<uint8_t> packet = std::move(command); packet.insert(packet.cbegin(), kH4Command); write_to_rootcanal_fd(packet); Loading @@ -106,7 +109,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { void sendAclData(HciPacket data) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); ASSERT(sock_fd_ != INVALID_FD); std::vector<uint8_t> packet = std::move(data); packet.insert(packet.cbegin(), kH4Acl); write_to_rootcanal_fd(packet); Loading @@ -114,7 +117,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { void sendScoData(HciPacket data) override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); ASSERT(sock_fd_ != INVALID_FD); std::vector<uint8_t> packet = std::move(data); packet.insert(packet.cbegin(), kH4Sco); write_to_rootcanal_fd(packet); Loading @@ -122,19 +125,22 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { void close() override { std::lock_guard<std::mutex> lock(mutex_); ASSERT(callback_ != nullptr); if (reactable_ != nullptr) { hci_incoming_thread_.GetReactor()->Unregister(reactable_); ASSERT(sock_fd_ != INVALID_FD); } reactable_ = nullptr; callback_ = nullptr; incoming_packet_callback_ = nullptr; ::close(sock_fd_); sock_fd_ = INVALID_FD; LOG_INFO("Rootcanal HAL is closed"); } private: std::mutex mutex_; HciHalHostRootcanalConfig* config_ = HciHalHostRootcanalConfig::Get(); BluetoothHciHalCallbacks* callback_ = nullptr; int sock_fd_ = 0; BluetoothHciHalCallbacks* incoming_packet_callback_ = nullptr; int sock_fd_ = INVALID_FD; bluetooth::os::Thread hci_incoming_thread_ = bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL); bluetooth::os::Reactor::Reactable* reactable_ = nullptr; Loading Loading @@ -163,6 +169,8 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { } void incoming_packet_received() { ASSERT(incoming_packet_callback_ != nullptr); uint8_t buf[kBufSize] = {}; ssize_t received_size; Loading @@ -188,7 +196,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size); callback_->hciEventReceived(receivedHciPacket); incoming_packet_callback_->hciEventReceived(receivedHciPacket); } if (buf[0] == kH4Acl) { Loading @@ -204,7 +212,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size); callback_->aclDataReceived(receivedHciPacket); incoming_packet_callback_->aclDataReceived(receivedHciPacket); } if (buf[0] == kH4Sco) { Loading @@ -217,7 +225,7 @@ class BluetoothHciHalHostRootcanal : public BluetoothHciHal { HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size); callback_->scoDataReceived(receivedHciPacket); incoming_packet_callback_->scoDataReceived(receivedHciPacket); } memset(buf, 0, kBufSize); } Loading
system/gd/hal/hci_hal_host_rootcanal_test.cc +7 −2 Original line number Diff line number Diff line Loading @@ -50,12 +50,15 @@ using H4Packet = std::vector<uint8_t>; std::queue<std::pair<uint8_t, HciPacket>> incoming_packets_queue_; class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks { class TestBluetoothInitializationCompleteCallback : public BluetoothInitializationCompleteCallback { public: void initializationComplete(Status status) override { EXPECT_EQ(status, Status::SUCCESS); } }; class TestBluetoothHciHalCallbacks : public BluetoothHciHalCallbacks { public: void hciEventReceived(HciPacket packet) override { incoming_packets_queue_.emplace(kH4Event, packet); } Loading Loading @@ -139,7 +142,8 @@ class HciHalRootcanalTest : public ::testing::Test { HciHalHostRootcanalConfig::Get()->SetPort(kTestPort); fake_server_ = new FakeRootcanalDesktopHciServer; hal_ = GetBluetoothHciHal(); hal_->initialize(&callbacks_); hal_->initialize(&init_callback_); hal_->registerIncomingPacketCallback(&callbacks_); fake_server_socket_ = fake_server_->Accept(); // accept() after client is connected to avoid blocking std::queue<std::pair<uint8_t, HciPacket>> empty; std::swap(incoming_packets_queue_, empty); Loading @@ -159,6 +163,7 @@ class HciHalRootcanalTest : public ::testing::Test { FakeRootcanalDesktopHciServer* fake_server_ = nullptr; BluetoothHciHal* hal_ = nullptr; TestBluetoothInitializationCompleteCallback init_callback_; TestBluetoothHciHalCallbacks callbacks_; int fake_server_socket_ = -1; }; Loading