mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge "BluetoothHAL: Reset the chip on open(), close once" am: 800e717e64 am: 4b63d5ae78 am: 326cf0f304
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2402198 Change-Id: I8ea21bde4b0fece02aedd5216f5a582bd73e8972 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -30,8 +30,15 @@ cc_library_static {
|
||||
defaults: ["android.hardware.bluetooth-service-build-defaults"],
|
||||
srcs: [
|
||||
"BluetoothHci.cpp",
|
||||
":BluetoothPacketSources",
|
||||
"net_bluetooth_mgmt.cpp",
|
||||
],
|
||||
generated_headers: [
|
||||
"BluetoothGeneratedPackets_h",
|
||||
],
|
||||
include_dirs: [
|
||||
"packages/modules/Bluetooth/system/gd",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
|
||||
#include "log/log.h"
|
||||
|
||||
// TODO: Remove custom logging defines from PDL packets.
|
||||
#undef LOG_INFO
|
||||
#undef LOG_DEBUG
|
||||
#include "hci/hci_packets.h"
|
||||
|
||||
namespace {
|
||||
int SetTerminalRaw(int fd) {
|
||||
termios terminal_settings;
|
||||
@@ -74,15 +79,22 @@ class BluetoothDeathRecipient {
|
||||
ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
|
||||
return;
|
||||
}
|
||||
has_died_ = true;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mHasDiedMutex);
|
||||
has_died_ = true;
|
||||
}
|
||||
mHci->close();
|
||||
}
|
||||
BluetoothHci* mHci;
|
||||
std::shared_ptr<IBluetoothHciCallbacks> mCb;
|
||||
AIBinder_DeathRecipient* clientDeathRecipient_;
|
||||
bool getHasDied() const { return has_died_; }
|
||||
bool getHasDied() {
|
||||
std::lock_guard<std::mutex> guard(mHasDiedMutex);
|
||||
return has_died_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mHasDiedMutex;
|
||||
bool has_died_{false};
|
||||
};
|
||||
|
||||
@@ -114,16 +126,95 @@ int BluetoothHci::getFdFromDevPath() {
|
||||
return fd;
|
||||
}
|
||||
|
||||
void BluetoothHci::reset() {
|
||||
// Send a reset command and wait until the command complete comes back.
|
||||
|
||||
std::vector<uint8_t> reset;
|
||||
::bluetooth::packet::BitInserter bi{reset};
|
||||
::bluetooth::hci::ResetBuilder::Create()->Serialize(bi);
|
||||
|
||||
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) {
|
||||
bool valid = ::bluetooth::hci::ResetCompleteView::Create(
|
||||
::bluetooth::hci::CommandCompleteView::Create(
|
||||
::bluetooth::hci::EventView::Create(
|
||||
::bluetooth::hci::PacketView<true>(
|
||||
std::make_shared<std::vector<uint8_t>>(
|
||||
raw_event)))))
|
||||
.IsValid();
|
||||
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(); });
|
||||
|
||||
send(PacketType::COMMAND, reset);
|
||||
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__);
|
||||
|
||||
mCb = cb;
|
||||
if (mCb == nullptr) {
|
||||
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) {
|
||||
@@ -132,12 +223,16 @@ ndk::ScopedAStatus BluetoothHci::initialize(
|
||||
ALOGI("Unable to open Linux interface, trying default path.");
|
||||
mFd = getFdFromDevPath();
|
||||
if (mFd < 0) {
|
||||
return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
|
||||
cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
}
|
||||
|
||||
mDeathRecipient->LinkToDeath(mCb);
|
||||
|
||||
// TODO: This should not be necessary when the device implements rfkill.
|
||||
reset();
|
||||
|
||||
mH4 = std::make_shared<H4Protocol>(
|
||||
mFd,
|
||||
[](const std::vector<uint8_t>& /* raw_command */) {
|
||||
@@ -162,6 +257,10 @@ ndk::ScopedAStatus BluetoothHci::initialize(
|
||||
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()) {
|
||||
@@ -178,13 +277,27 @@ ndk::ScopedAStatus BluetoothHci::initialize(
|
||||
|
||||
ndk::ScopedAStatus BluetoothHci::close() {
|
||||
ALOGI(__func__);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mStateMutex);
|
||||
if (mState != HalState::ONE_CLIENT) {
|
||||
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;
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
|
||||
#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include <future>
|
||||
#include <string>
|
||||
|
||||
#include "async_fd_watcher.h"
|
||||
@@ -69,6 +69,18 @@ class BluetoothHci : public BnBluetoothHci {
|
||||
void 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
|
||||
|
||||
@@ -201,7 +201,6 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> {
|
||||
void sendAndCheckAcl(int num_packets, size_t size, uint16_t handle);
|
||||
|
||||
// Helper functions to try to get a handle on verbosity
|
||||
void reset();
|
||||
void enterLoopbackMode();
|
||||
void handle_no_ops();
|
||||
void discard_qca_debugging();
|
||||
@@ -610,12 +609,15 @@ void BluetoothAidlTest::sendAndCheckAcl(int num_packets, size_t size,
|
||||
// Return the number of completed packets reported by the controller.
|
||||
int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) {
|
||||
int packets_processed = 0;
|
||||
wait_for_event(false);
|
||||
if (event_queue.empty()) {
|
||||
ALOGW("%s: waitForBluetoothCallback timed out.", __func__);
|
||||
return packets_processed;
|
||||
}
|
||||
while (!event_queue.empty()) {
|
||||
while (true) {
|
||||
// There should be at least one event.
|
||||
wait_for_event(packets_processed == 0);
|
||||
if (event_queue.empty()) {
|
||||
if (packets_processed == 0) {
|
||||
ALOGW("%s: waitForBluetoothCallback timed out.", __func__);
|
||||
}
|
||||
return packets_processed;
|
||||
}
|
||||
std::vector<uint8_t> event;
|
||||
EXPECT_TRUE(event_queue.pop(event));
|
||||
|
||||
@@ -630,15 +632,6 @@ int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) {
|
||||
return packets_processed;
|
||||
}
|
||||
|
||||
// Send the reset command and wait for a response.
|
||||
void BluetoothAidlTest::reset() {
|
||||
std::vector<uint8_t> reset{kCommandHciReset,
|
||||
kCommandHciReset + sizeof(kCommandHciReset)};
|
||||
hci->sendHciCommand(reset);
|
||||
|
||||
wait_for_command_complete_event(reset);
|
||||
}
|
||||
|
||||
// Send local loopback command and initialize SCO and ACL handles.
|
||||
void BluetoothAidlTest::enterLoopbackMode() {
|
||||
std::vector<uint8_t> cmd{kCommandHciWriteLoopbackModeLocal,
|
||||
@@ -696,11 +689,16 @@ void BluetoothAidlTest::enterLoopbackMode() {
|
||||
TEST_P(BluetoothAidlTest, InitializeAndClose) {}
|
||||
|
||||
// Send an HCI Reset with sendHciCommand and wait for a command complete event.
|
||||
TEST_P(BluetoothAidlTest, HciReset) { reset(); }
|
||||
TEST_P(BluetoothAidlTest, HciReset) {
|
||||
std::vector<uint8_t> reset{kCommandHciReset,
|
||||
kCommandHciReset + sizeof(kCommandHciReset)};
|
||||
hci->sendHciCommand(reset);
|
||||
|
||||
wait_for_command_complete_event(reset);
|
||||
}
|
||||
|
||||
// Read and check the HCI version of the controller.
|
||||
TEST_P(BluetoothAidlTest, HciVersionTest) {
|
||||
reset();
|
||||
std::vector<uint8_t> cmd{kCommandHciReadLocalVersionInformation,
|
||||
kCommandHciReadLocalVersionInformation +
|
||||
sizeof(kCommandHciReadLocalVersionInformation)};
|
||||
@@ -723,7 +721,6 @@ TEST_P(BluetoothAidlTest, HciVersionTest) {
|
||||
|
||||
// Send an unknown HCI command and wait for the error message.
|
||||
TEST_P(BluetoothAidlTest, HciUnknownCommand) {
|
||||
reset();
|
||||
std::vector<uint8_t> cmd{
|
||||
kCommandHciShouldBeUnknown,
|
||||
kCommandHciShouldBeUnknown + sizeof(kCommandHciShouldBeUnknown)};
|
||||
@@ -750,14 +747,10 @@ TEST_P(BluetoothAidlTest, HciUnknownCommand) {
|
||||
}
|
||||
|
||||
// Enter loopback mode, but don't send any packets.
|
||||
TEST_P(BluetoothAidlTest, WriteLoopbackMode) {
|
||||
reset();
|
||||
enterLoopbackMode();
|
||||
}
|
||||
TEST_P(BluetoothAidlTest, WriteLoopbackMode) { enterLoopbackMode(); }
|
||||
|
||||
// Enter loopback mode and send a single command.
|
||||
TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) {
|
||||
reset();
|
||||
setBufferSizes();
|
||||
|
||||
enterLoopbackMode();
|
||||
@@ -767,7 +760,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) {
|
||||
|
||||
// Enter loopback mode and send a single SCO packet.
|
||||
TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) {
|
||||
reset();
|
||||
setBufferSizes();
|
||||
setSynchronousFlowControlEnable();
|
||||
|
||||
@@ -788,7 +780,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) {
|
||||
|
||||
// Enter loopback mode and send a single ACL packet.
|
||||
TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) {
|
||||
reset();
|
||||
setBufferSizes();
|
||||
|
||||
enterLoopbackMode();
|
||||
@@ -810,7 +801,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) {
|
||||
|
||||
// Enter loopback mode and send command packets for bandwidth measurements.
|
||||
TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) {
|
||||
reset();
|
||||
setBufferSizes();
|
||||
|
||||
enterLoopbackMode();
|
||||
@@ -820,7 +810,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) {
|
||||
|
||||
// Enter loopback mode and send SCO packets for bandwidth measurements.
|
||||
TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) {
|
||||
reset();
|
||||
setBufferSizes();
|
||||
setSynchronousFlowControlEnable();
|
||||
|
||||
@@ -842,7 +831,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) {
|
||||
|
||||
// Enter loopback mode and send packets for ACL bandwidth measurements.
|
||||
TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) {
|
||||
reset();
|
||||
setBufferSizes();
|
||||
|
||||
enterLoopbackMode();
|
||||
@@ -863,7 +851,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) {
|
||||
|
||||
// Set all bits in the event mask
|
||||
TEST_P(BluetoothAidlTest, SetEventMask) {
|
||||
reset();
|
||||
std::vector<uint8_t> set_event_mask{
|
||||
0x01, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff};
|
||||
@@ -873,7 +860,6 @@ TEST_P(BluetoothAidlTest, SetEventMask) {
|
||||
|
||||
// Set all bits in the LE event mask
|
||||
TEST_P(BluetoothAidlTest, SetLeEventMask) {
|
||||
reset();
|
||||
std::vector<uint8_t> set_event_mask{
|
||||
0x20, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff};
|
||||
|
||||
Reference in New Issue
Block a user