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

Commit c6f9e6f9 authored by Myles Watson's avatar Myles Watson Committed by Automerger Merge Worker
Browse files

Merge "Bluetooth HAL: Add AIDL support" am: 948e06fb

parents bea491b4 948e06fb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -170,6 +170,9 @@ cc_defaults {
                "libutils",
                "libstatslog_bt",
            ],
            whole_static_libs: [
                "android.hardware.bluetooth-V1-ndk",
            ],
        },
    },
    srcs: [
+262 −20
Original line number Diff line number Diff line
@@ -14,12 +14,24 @@
 * limitations under the License.
 */

#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/BnBluetoothHciCallbacks.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHci.h>
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android/hardware/bluetooth/1.0/types.h>
#include <android/hardware/bluetooth/1.1/IBluetoothHci.h>
#include <android/hardware/bluetooth/1.1/IBluetoothHciCallbacks.h>
#include <stdlib.h>

// AIDL uses syslog.h, so these defines conflict with os/log.h
#undef LOG_DEBUG
#undef LOG_INFO
#undef LOG_WARNING

#include <future>
#include <mutex>
#include <vector>

#include "btaa/activity_attribution.h"
@@ -35,9 +47,11 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::bluetooth::V1_1::IBluetoothHci;
using ::android::hardware::bluetooth::V1_1::IBluetoothHciCallbacks;
using IBluetoothHci_1_1 = ::android::hardware::bluetooth::V1_1::IBluetoothHci;
using IBluetoothHciCallbacks_1_1 = ::android::hardware::bluetooth::V1_1::IBluetoothHciCallbacks;
using HidlStatus = ::android::hardware::bluetooth::V1_0::Status;
using aidl::android::hardware::bluetooth::IBluetoothHci;
using AidlStatus = ::aidl::android::hardware::bluetooth::Status;
using IBluetoothHci_1_0 = ::android::hardware::bluetooth::V1_0::IBluetoothHci;
using bluetooth::common::BindOnce;

@@ -65,7 +79,7 @@ std::string GetTimerText(const char* func_name, VecType vec) {
      common::ToHexString(vec.begin(), std::min(vec.end(), vec.begin() + 5)).c_str());
}

class InternalHciCallbacks : public IBluetoothHciCallbacks {
class InternalHciCallbacks : public IBluetoothHciCallbacks_1_1 {
 public:
  InternalHciCallbacks(activity_attribution::ActivityAttribution* btaa_logger_, SnoopLogger* btsnoop_logger)
      : btaa_logger_(btaa_logger_), btsnoop_logger_(btsnoop_logger) {
@@ -167,51 +181,203 @@ class InternalHciCallbacks : public IBluetoothHciCallbacks {
  SnoopLogger* btsnoop_logger_ = nullptr;
};

static constexpr char kBluetoothAidlHalServiceName[] =
    "android.hardware.bluetooth.IBluetoothHci/default";

class AidlHciCallbacks : public ::aidl::android::hardware::bluetooth::BnBluetoothHciCallbacks {
 public:
  AidlHciCallbacks(
      activity_attribution::ActivityAttribution* btaa_logger_, SnoopLogger* btsnoop_logger)
      : btaa_logger_(btaa_logger_), btsnoop_logger_(btsnoop_logger) {
    init_promise_ = new std::promise<void>();
  }

  void SetCallback(HciHalCallbacks* callback) {
    std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
    ASSERT(callback_ == nullptr && callback != nullptr);
    callback_ = callback;
  }

  void ResetCallback() {
    std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
    callback_ = nullptr;
  }

  std::promise<void>* GetInitPromise() {
    return init_promise_;
  }

  ::ndk::ScopedAStatus initializationComplete(AidlStatus status) {
    common::StopWatch stop_watch(__func__);
    ASSERT(status == AidlStatus::SUCCESS);
    init_promise_->set_value();
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& event) override {
    common::StopWatch stop_watch(GetTimerText(__func__, event));
    std::vector<uint8_t> received_hci_packet(event.begin(), event.end());
    btsnoop_logger_->Capture(
        received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_->Capture(received_hci_packet, SnoopLogger::PacketType::EVT);
    }
    bool sent = false;
    {
      std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
      if (callback_ != nullptr) {
        callback_->hciEventReceived(std::move(received_hci_packet));
        sent = true;
      }
    }
    if (!sent) {
      LOG_INFO("Dropping HCI Event, since callback_ is null");
    }
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus aclDataReceived(const std::vector<uint8_t>& data) override {
    common::StopWatch stop_watch(GetTimerText(__func__, data));
    std::vector<uint8_t> received_hci_packet(data.begin(), data.end());
    btsnoop_logger_->Capture(
        received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_->Capture(received_hci_packet, SnoopLogger::PacketType::ACL);
    }
    bool sent = false;
    {
      std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
      if (callback_ != nullptr) {
        callback_->aclDataReceived(std::move(received_hci_packet));
        sent = true;
      }
    }
    if (!sent) {
      LOG_INFO("Dropping ACL Data, since callback_ is null");
    }
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus scoDataReceived(const std::vector<uint8_t>& data) override {
    common::StopWatch stop_watch(GetTimerText(__func__, data));
    std::vector<uint8_t> received_hci_packet(data.begin(), data.end());
    btsnoop_logger_->Capture(
        received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::SCO);
    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_->Capture(received_hci_packet, SnoopLogger::PacketType::SCO);
    }
    bool sent = false;
    {
      std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
      if (callback_ != nullptr) {
        callback_->scoDataReceived(std::move(received_hci_packet));
        sent = true;
      }
    }
    if (!sent) {
      LOG_INFO("Dropping SCO Data, since callback_ is null");
    }
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus isoDataReceived(const std::vector<uint8_t>& data) override {
    common::StopWatch stop_watch(GetTimerText(__func__, data));
    std::vector<uint8_t> received_hci_packet(data.begin(), data.end());
    btsnoop_logger_->Capture(
        received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ISO);
    bool sent = false;
    {
      std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
      if (callback_ != nullptr) {
        callback_->isoDataReceived(std::move(received_hci_packet));
        sent = true;
      }
    }
    if (!sent) {
      LOG_INFO("Dropping ISO Data, since callback_ is null");
    }
    return ::ndk::ScopedAStatus::ok();
  }

 private:
  std::mutex incoming_packet_callback_mutex_;
  std::promise<void>* init_promise_ = nullptr;
  HciHalCallbacks* callback_ = nullptr;
  activity_attribution::ActivityAttribution* btaa_logger_ = nullptr;
  SnoopLogger* btsnoop_logger_ = nullptr;
};

}  // namespace

class HciHalHidl : public HciHal {
 public:
  void registerIncomingPacketCallback(HciHalCallbacks* callback) override {
    if (aidl_callbacks_) {
      aidl_callbacks_->SetCallback(callback);
    }
    if (callbacks_) {
      callbacks_->SetCallback(callback);
    }
  }

  void unregisterIncomingPacketCallback() override {
    if (aidl_callbacks_) {
      aidl_callbacks_->ResetCallback();
    }
    if (callbacks_) {
      callbacks_->ResetCallback();
    }
  }

  void sendHciCommand(HciPacket command) override {
    btsnoop_logger_->Capture(command, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_->Capture(command, SnoopLogger::PacketType::CMD);
    }
    if (aidl_hci_) {
      aidl_hci_->sendHciCommand(command);
    } else {
      bt_hci_->sendHciCommand(command);
    }
  }

  void sendAclData(HciPacket packet) override {
    btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_->Capture(packet, SnoopLogger::PacketType::ACL);
    }
    if (aidl_hci_) {
      aidl_hci_->sendAclData(packet);
    } else {
      bt_hci_->sendAclData(packet);
    }
  }

  void sendScoData(HciPacket packet) override {
    btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::SCO);
    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_->Capture(packet, SnoopLogger::PacketType::SCO);
    }
    if (aidl_hci_) {
      aidl_hci_->sendScoData(packet);
    } else {
      bt_hci_->sendScoData(packet);
    }
  }

  void sendIsoData(HciPacket packet) override {
    if (bt_hci_1_1_ == nullptr) {
    if (aidl_hci_ == nullptr && bt_hci_1_1_ == nullptr) {
      LOG_ERROR("ISO is not supported in HAL v1.0");
      return;
    }

    btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ISO);
    if (aidl_hci_) {
      aidl_hci_->sendIsoData(packet);
    } else {
      bt_hci_1_1_->sendIsoData(packet);
    }
  }

 protected:
  void ListDependencies(ModuleList* list) const {
@@ -222,11 +388,53 @@ class HciHalHidl : public HciHal {
  }

  void Start() override {
    common::StopWatch stop_watch(__func__);

    // Start can't be called more than once before Stop is called.
    ASSERT(bt_hci_ == nullptr);
    ASSERT(bt_hci_1_1_ == nullptr);
    ASSERT(aidl_hci_ == nullptr);

    if (common::init_flags::btaa_hci_is_enabled()) {
      btaa_logger_ = GetDependency<activity_attribution::ActivityAttribution>();
    }
    btsnoop_logger_ = GetDependency<SnoopLogger>();

    if (AServiceManager_isDeclared(kBluetoothAidlHalServiceName)) {
      start_aidl();
      aidl_callbacks_->GetInitPromise()->get_future().wait();
    } else {
      start_hidl();
      callbacks_->GetInitPromise()->get_future().wait();
    }
  }

  void start_aidl() {
    common::StopWatch stop_watch(__func__);
    ::ndk::SpAIBinder binder(AServiceManager_getService(kBluetoothAidlHalServiceName));
    aidl_hci_ = IBluetoothHci::fromBinder(binder);
    if (aidl_hci_ != nullptr) {
      LOG_INFO("Using the AIDL interface");
      aidl_death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
          AIBinder_DeathRecipient_new(HciHalHidl::hci_binder_died_static));

      auto death_link =
          AIBinder_linkToDeath(aidl_hci_->asBinder().get(), aidl_death_recipient_.get(), this);

      ASSERT_LOG(
          death_link == STATUS_OK, "Unable to set the death recipient for the Bluetooth HAL");

      aidl_callbacks_ = ::ndk::SharedRefBase::make<AidlHciCallbacks>(btaa_logger_, btsnoop_logger_);
      aidl_hci_->initialize(aidl_callbacks_);
      return;
    }
  }

  void start_hidl() {
    common::StopWatch stop_watch(__func__);

    LOG_INFO("Trying to find a HIDL interface");

    auto get_service_alarm = new os::Alarm(GetHandler());
    get_service_alarm->Schedule(
        BindOnce([] {
@@ -243,7 +451,7 @@ class HciHalHidl : public HciHal {
        }),
        std::chrono::milliseconds(500));

    bt_hci_1_1_ = IBluetoothHci::getService();
    bt_hci_1_1_ = IBluetoothHci_1_1::getService();

    if (bt_hci_1_1_ != nullptr) {
      bt_hci_ = bt_hci_1_1_;
@@ -264,12 +472,34 @@ class HciHalHidl : public HciHal {
    } else {
      bt_hci_->initialize(callbacks_);
    }

    // Don't timeout here, time out at a higher layer
    callbacks_->GetInitPromise()->get_future().wait();
  }

  void Stop() override {
    if (bt_hci_ != nullptr) {
      stop_hidl();
    }
    if (aidl_hci_ != nullptr) {
      stop_aidl();
    }
  }

  std::string ToString() const override {
    return std::string("HciHalHidl");
  }

 private:
  static void hci_binder_died_static(void* cookie) {
    auto hal_ptr = static_cast<HciHalHidl*>(cookie);
    hal_ptr->hci_binder_died();
  }

  void hci_binder_died() {
    LOG_ERROR("Bluetooth HAL service died!");
    common::StopWatch::DumpStopWatchLog();
    abort();
  }

  void stop_hidl() {
    ASSERT(bt_hci_ != nullptr);
    auto death_unlink = bt_hci_->unlinkToDeath(hci_death_recipient_);
    if (!death_unlink.isOk()) {
@@ -279,19 +509,31 @@ class HciHalHidl : public HciHal {
    if (!close_status.isOk()) {
      LOG_ERROR("Error calling close on the Bluetooth HAL");
    }
    callbacks_->ResetCallback();
    bt_hci_ = nullptr;
    bt_hci_1_1_ = nullptr;
    callbacks_->ResetCallback();
  }

  std::string ToString() const override {
    return std::string("HciHalHidl");
  void stop_aidl() {
    ASSERT(aidl_hci_ != nullptr);
    auto death_unlink =
        AIBinder_unlinkToDeath(aidl_hci_->asBinder().get(), aidl_death_recipient_.get(), this);
    if (death_unlink != STATUS_OK) {
      LOG_ERROR("Error unlinking death recipient from the Bluetooth HAL");
    }
    auto close_status = aidl_hci_->close();
    if (!close_status.isOk()) {
      LOG_ERROR("Error calling close on the Bluetooth HAL");
    }
    aidl_hci_ = nullptr;
    aidl_callbacks_->ResetCallback();
  }

 private:
  android::sp<InternalHciCallbacks> callbacks_;
  android::sp<IBluetoothHci_1_0> bt_hci_;
  android::sp<IBluetoothHci> bt_hci_1_1_;
  android::sp<IBluetoothHci_1_1> bt_hci_1_1_;
  std::shared_ptr<IBluetoothHci> aidl_hci_;
  std::shared_ptr<AidlHciCallbacks> aidl_callbacks_;
  ::ndk::ScopedAIBinder_DeathRecipient aidl_death_recipient_;
  activity_attribution::ActivityAttribution* btaa_logger_;
  SnoopLogger* btsnoop_logger_;
};