Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 800e717e authored by Myles Watson's avatar Myles Watson Committed by Gerrit Code Review
Browse files

Merge "BluetoothHAL: Reset the chip on open(), close once"

parents f784df7c 65b47f5f
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -30,8 +30,15 @@ cc_library_static {
    defaults: ["android.hardware.bluetooth-service-build-defaults"],
    defaults: ["android.hardware.bluetooth-service-build-defaults"],
    srcs: [
    srcs: [
        "BluetoothHci.cpp",
        "BluetoothHci.cpp",
        ":BluetoothPacketSources",
        "net_bluetooth_mgmt.cpp",
        "net_bluetooth_mgmt.cpp",
    ],
    ],
    generated_headers: [
        "BluetoothGeneratedPackets_h",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system/gd",
    ],
}
}


cc_binary {
cc_binary {
+118 −5
Original line number Original line Diff line number Diff line
@@ -29,6 +29,11 @@


#include "log/log.h"
#include "log/log.h"


// TODO: Remove custom logging defines from PDL packets.
#undef LOG_INFO
#undef LOG_DEBUG
#include "hci/hci_packets.h"

namespace {
namespace {
int SetTerminalRaw(int fd) {
int SetTerminalRaw(int fd) {
  termios terminal_settings;
  termios terminal_settings;
@@ -74,15 +79,22 @@ class BluetoothDeathRecipient {
      ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
      ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
      return;
      return;
    }
    }
    {
      std::lock_guard<std::mutex> guard(mHasDiedMutex);
      has_died_ = true;
      has_died_ = true;
    }
    mHci->close();
    mHci->close();
  }
  }
  BluetoothHci* mHci;
  BluetoothHci* mHci;
  std::shared_ptr<IBluetoothHciCallbacks> mCb;
  std::shared_ptr<IBluetoothHciCallbacks> mCb;
  AIBinder_DeathRecipient* clientDeathRecipient_;
  AIBinder_DeathRecipient* clientDeathRecipient_;
  bool getHasDied() const { return has_died_; }
  bool getHasDied() {
    std::lock_guard<std::mutex> guard(mHasDiedMutex);
    return has_died_;
  }


 private:
 private:
  std::mutex mHasDiedMutex;
  bool has_died_{false};
  bool has_died_{false};
};
};


@@ -114,16 +126,95 @@ int BluetoothHci::getFdFromDevPath() {
  return fd;
  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(
ndk::ScopedAStatus BluetoothHci::initialize(
    const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
    const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
  ALOGI(__func__);
  ALOGI(__func__);


  mCb = cb;
  if (cb == nullptr) {
  if (mCb == nullptr) {
    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
    return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
    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);
  management_.reset(new NetBluetoothMgmt);
  mFd = management_->openHci();
  mFd = management_->openHci();
  if (mFd < 0) {
  if (mFd < 0) {
@@ -132,12 +223,16 @@ ndk::ScopedAStatus BluetoothHci::initialize(
    ALOGI("Unable to open Linux interface, trying default path.");
    ALOGI("Unable to open Linux interface, trying default path.");
    mFd = getFdFromDevPath();
    mFd = getFdFromDevPath();
    if (mFd < 0) {
    if (mFd < 0) {
      return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
      cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
      return ndk::ScopedAStatus::ok();
    }
    }
  }
  }


  mDeathRecipient->LinkToDeath(mCb);
  mDeathRecipient->LinkToDeath(mCb);


  // TODO: This should not be necessary when the device implements rfkill.
  reset();

  mH4 = std::make_shared<H4Protocol>(
  mH4 = std::make_shared<H4Protocol>(
      mFd,
      mFd,
      [](const std::vector<uint8_t>& /* raw_command */) {
      [](const std::vector<uint8_t>& /* raw_command */) {
@@ -162,6 +257,10 @@ ndk::ScopedAStatus BluetoothHci::initialize(
  mFdWatcher.WatchFdForNonBlockingReads(mFd,
  mFdWatcher.WatchFdForNonBlockingReads(mFd,
                                        [this](int) { mH4->OnDataReady(); });
                                        [this](int) { mH4->OnDataReady(); });


  {
    std::lock_guard<std::mutex> guard(mStateMutex);
    mState = HalState::ONE_CLIENT;
  }
  ALOGI("initialization complete");
  ALOGI("initialization complete");
  auto status = mCb->initializationComplete(Status::SUCCESS);
  auto status = mCb->initializationComplete(Status::SUCCESS);
  if (!status.isOk()) {
  if (!status.isOk()) {
@@ -178,13 +277,27 @@ ndk::ScopedAStatus BluetoothHci::initialize(


ndk::ScopedAStatus BluetoothHci::close() {
ndk::ScopedAStatus BluetoothHci::close() {
  ALOGI(__func__);
  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();
  mFdWatcher.StopWatchingFileDescriptors();

  if (management_) {
  if (management_) {
    management_->closeHci();
    management_->closeHci();
  } else {
  } else {
    ::close(mFd);
    ::close(mFd);
  }
  }


  {
    std::lock_guard<std::mutex> guard(mStateMutex);
    mState = HalState::READY;
  }
  return ndk::ScopedAStatus::ok();
  return ndk::ScopedAStatus::ok();
}
}


+13 −1
Original line number Original line Diff line number Diff line
@@ -18,8 +18,8 @@


#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
#include <log/log.h>


#include <future>
#include <string>
#include <string>


#include "async_fd_watcher.h"
#include "async_fd_watcher.h"
@@ -69,6 +69,18 @@ class BluetoothHci : public BnBluetoothHci {
  void send(::android::hardware::bluetooth::hci::PacketType type,
  void send(::android::hardware::bluetooth::hci::PacketType type,
            const std::vector<uint8_t>& packet);
            const std::vector<uint8_t>& packet);
  std::unique_ptr<NetBluetoothMgmt> management_{};
  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
}  // namespace aidl::android::hardware::bluetooth::impl
+17 −31
Original line number Original line Diff line number Diff line
@@ -201,7 +201,6 @@ class BluetoothAidlTest : public ::testing::TestWithParam<std::string> {
  void sendAndCheckAcl(int num_packets, size_t size, uint16_t handle);
  void sendAndCheckAcl(int num_packets, size_t size, uint16_t handle);


  // Helper functions to try to get a handle on verbosity
  // Helper functions to try to get a handle on verbosity
  void reset();
  void enterLoopbackMode();
  void enterLoopbackMode();
  void handle_no_ops();
  void handle_no_ops();
  void discard_qca_debugging();
  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.
// Return the number of completed packets reported by the controller.
int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) {
int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) {
  int packets_processed = 0;
  int packets_processed = 0;
  wait_for_event(false);
  while (true) {
    // There should be at least one event.
    wait_for_event(packets_processed == 0);
    if (event_queue.empty()) {
    if (event_queue.empty()) {
      if (packets_processed == 0) {
        ALOGW("%s: waitForBluetoothCallback timed out.", __func__);
        ALOGW("%s: waitForBluetoothCallback timed out.", __func__);
      }
      return packets_processed;
      return packets_processed;
    }
    }
  while (!event_queue.empty()) {
    std::vector<uint8_t> event;
    std::vector<uint8_t> event;
    EXPECT_TRUE(event_queue.pop(event));
    EXPECT_TRUE(event_queue.pop(event));


@@ -630,15 +632,6 @@ int BluetoothAidlTest::wait_for_completed_packets_event(uint16_t handle) {
  return packets_processed;
  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.
// Send local loopback command and initialize SCO and ACL handles.
void BluetoothAidlTest::enterLoopbackMode() {
void BluetoothAidlTest::enterLoopbackMode() {
  std::vector<uint8_t> cmd{kCommandHciWriteLoopbackModeLocal,
  std::vector<uint8_t> cmd{kCommandHciWriteLoopbackModeLocal,
@@ -696,11 +689,16 @@ void BluetoothAidlTest::enterLoopbackMode() {
TEST_P(BluetoothAidlTest, InitializeAndClose) {}
TEST_P(BluetoothAidlTest, InitializeAndClose) {}


// Send an HCI Reset with sendHciCommand and wait for a command complete event.
// 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.
// Read and check the HCI version of the controller.
TEST_P(BluetoothAidlTest, HciVersionTest) {
TEST_P(BluetoothAidlTest, HciVersionTest) {
  reset();
  std::vector<uint8_t> cmd{kCommandHciReadLocalVersionInformation,
  std::vector<uint8_t> cmd{kCommandHciReadLocalVersionInformation,
                           kCommandHciReadLocalVersionInformation +
                           kCommandHciReadLocalVersionInformation +
                               sizeof(kCommandHciReadLocalVersionInformation)};
                               sizeof(kCommandHciReadLocalVersionInformation)};
@@ -723,7 +721,6 @@ TEST_P(BluetoothAidlTest, HciVersionTest) {


// Send an unknown HCI command and wait for the error message.
// Send an unknown HCI command and wait for the error message.
TEST_P(BluetoothAidlTest, HciUnknownCommand) {
TEST_P(BluetoothAidlTest, HciUnknownCommand) {
  reset();
  std::vector<uint8_t> cmd{
  std::vector<uint8_t> cmd{
      kCommandHciShouldBeUnknown,
      kCommandHciShouldBeUnknown,
      kCommandHciShouldBeUnknown + sizeof(kCommandHciShouldBeUnknown)};
      kCommandHciShouldBeUnknown + sizeof(kCommandHciShouldBeUnknown)};
@@ -750,14 +747,10 @@ TEST_P(BluetoothAidlTest, HciUnknownCommand) {
}
}


// Enter loopback mode, but don't send any packets.
// Enter loopback mode, but don't send any packets.
TEST_P(BluetoothAidlTest, WriteLoopbackMode) {
TEST_P(BluetoothAidlTest, WriteLoopbackMode) { enterLoopbackMode(); }
  reset();
  enterLoopbackMode();
}


// Enter loopback mode and send a single command.
// Enter loopback mode and send a single command.
TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) {
TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) {
  reset();
  setBufferSizes();
  setBufferSizes();


  enterLoopbackMode();
  enterLoopbackMode();
@@ -767,7 +760,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeSingleCommand) {


// Enter loopback mode and send a single SCO packet.
// Enter loopback mode and send a single SCO packet.
TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) {
TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) {
  reset();
  setBufferSizes();
  setBufferSizes();
  setSynchronousFlowControlEnable();
  setSynchronousFlowControlEnable();


@@ -788,7 +780,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) {


// Enter loopback mode and send a single ACL packet.
// Enter loopback mode and send a single ACL packet.
TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) {
TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) {
  reset();
  setBufferSizes();
  setBufferSizes();


  enterLoopbackMode();
  enterLoopbackMode();
@@ -810,7 +801,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) {


// Enter loopback mode and send command packets for bandwidth measurements.
// Enter loopback mode and send command packets for bandwidth measurements.
TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) {
TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) {
  reset();
  setBufferSizes();
  setBufferSizes();


  enterLoopbackMode();
  enterLoopbackMode();
@@ -820,7 +810,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeCommandBandwidth) {


// Enter loopback mode and send SCO packets for bandwidth measurements.
// Enter loopback mode and send SCO packets for bandwidth measurements.
TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) {
TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) {
  reset();
  setBufferSizes();
  setBufferSizes();
  setSynchronousFlowControlEnable();
  setSynchronousFlowControlEnable();


@@ -842,7 +831,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) {


// Enter loopback mode and send packets for ACL bandwidth measurements.
// Enter loopback mode and send packets for ACL bandwidth measurements.
TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) {
TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) {
  reset();
  setBufferSizes();
  setBufferSizes();


  enterLoopbackMode();
  enterLoopbackMode();
@@ -863,7 +851,6 @@ TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) {


// Set all bits in the event mask
// Set all bits in the event mask
TEST_P(BluetoothAidlTest, SetEventMask) {
TEST_P(BluetoothAidlTest, SetEventMask) {
  reset();
  std::vector<uint8_t> set_event_mask{
  std::vector<uint8_t> set_event_mask{
      0x01, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0x01, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff};
      0xff, 0xff};
@@ -873,7 +860,6 @@ TEST_P(BluetoothAidlTest, SetEventMask) {


// Set all bits in the LE event mask
// Set all bits in the LE event mask
TEST_P(BluetoothAidlTest, SetLeEventMask) {
TEST_P(BluetoothAidlTest, SetLeEventMask) {
  reset();
  std::vector<uint8_t> set_event_mask{
  std::vector<uint8_t> set_event_mask{
      0x20, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0x20, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff};
      0xff, 0xff};