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

Commit 3ba15b62 authored by Antoine SOULIER's avatar Antoine SOULIER
Browse files

hci/hal: Separate AIDL/HIDL in the HAL

Bug: 333612868
Test: mmm packages/modules/Bluetooth
Flag: EXEMPT, code move
Change-Id: I23e36af000f8a6c527d1488490079e94d7d8bad7
parent e73086e3
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -433,7 +433,6 @@ cc_test {
        },
        android: {
            srcs: [
                ":BluetoothHalTestSources_hci_android_hidl",
                ":BluetoothOsTestSources_android",
            ],
            static_libs: [
+3 −8
Original line number Diff line number Diff line
@@ -37,7 +37,9 @@ filegroup {
filegroup {
    name: "BluetoothHalSources_hci_android_hidl",
    srcs: [
        "hci_hal_android_hidl.cc",
        "hci_backend_aidl.cc",
        "hci_backend_hidl.cc",
        "hci_hal_android.cc",
    ],
}

@@ -48,13 +50,6 @@ filegroup {
    ],
}

filegroup {
    name: "BluetoothHalTestSources_hci_android_hidl",
    srcs: [
        "hci_hal_android_hidl_test.cc",
    ],
}

filegroup {
    name: "BluetoothHalFake",
    srcs: [
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 * 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.
@@ -14,38 +14,41 @@
 * limitations under the License.
 */

#include <gtest/gtest.h>
#pragma once

#include <chrono>
#include <future>
#include <cstdint>
#include <memory>
#include <vector>

#include "hal/hci_hal.h"
#include "os/thread.h"
// syslog.h conflicts with os/*.h
#undef LOG_DEBUG
#undef LOG_INFO
#undef LOG_WARNING
#include "os/handler.h"

using ::bluetooth::os::Thread;
namespace bluetooth::hal {

namespace bluetooth {
namespace hal {
namespace {

class HciHalHidlTest : public ::testing::Test {
 protected:
  void SetUp() override {
    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
  }

  void TearDown() override {
    delete thread_;
  }
class HciBackendCallbacks {
 public:
  virtual ~HciBackendCallbacks() = default;
  virtual void initializationComplete(void) = 0;
  virtual void hciEventReceived(const std::vector<uint8_t>&) = 0;
  virtual void aclDataReceived(const std::vector<uint8_t>&) = 0;
  virtual void scoDataReceived(const std::vector<uint8_t>&) = 0;
  virtual void isoDataReceived(const std::vector<uint8_t>&) = 0;
};

  ModuleRegistry fake_registry_;
  Thread* thread_;
class HciBackend {
 public:
  static std::shared_ptr<HciBackend> CreateAidl(const char*);
  static std::shared_ptr<HciBackend> CreateHidl(::bluetooth::os::Handler*);

  virtual ~HciBackend() = default;
  virtual void initialize(std::shared_ptr<HciBackendCallbacks>) = 0;
  virtual void sendHciCommand(const std::vector<uint8_t>&) = 0;
  virtual void sendAclData(const std::vector<uint8_t>&) = 0;
  virtual void sendScoData(const std::vector<uint8_t>&) = 0;
  virtual void sendIsoData(const std::vector<uint8_t>&) = 0;
};

TEST_F(HciHalHidlTest, init_and_close) {
  fake_registry_.Start<HciHal>(thread_);
  fake_registry_.StopAll();
}
}  // namespace
}  // namespace hal
}  // namespace bluetooth
}  // namespace bluetooth::hal
+129 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/BnBluetoothHciCallbacks.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHci.h>
#include <android/binder_manager.h>
#include <bluetooth/log.h>

#include "common/stop_watch.h"
#include "hal/hci_backend.h"

namespace bluetooth::hal {

class AidlHciCallbacks : public ::aidl::android::hardware::bluetooth::BnBluetoothHciCallbacks {
 public:
  AidlHciCallbacks(std::shared_ptr<HciBackendCallbacks> callbacks) : callbacks_(callbacks) {}

  using AidlStatus = ::aidl::android::hardware::bluetooth::Status;
  ::ndk::ScopedAStatus initializationComplete(AidlStatus status) override {
    log::assert_that(status == AidlStatus::SUCCESS, "status == AidlStatus::SUCCESS");
    callbacks_->initializationComplete();
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& packet) override {
    callbacks_->hciEventReceived(packet);
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus aclDataReceived(const std::vector<uint8_t>& packet) override {
    callbacks_->aclDataReceived(packet);
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus scoDataReceived(const std::vector<uint8_t>& packet) override {
    callbacks_->scoDataReceived(packet);
    return ::ndk::ScopedAStatus::ok();
  }

  ::ndk::ScopedAStatus isoDataReceived(const std::vector<uint8_t>& packet) override {
    callbacks_->isoDataReceived(packet);
    return ::ndk::ScopedAStatus::ok();
  }

 private:
  std::shared_ptr<HciBackendCallbacks> callbacks_;
};

class AidlHci : public HciBackend {
 public:
  AidlHci(const char* service_name) {
    common::StopWatch stop_watch(__func__);

    ::ndk::SpAIBinder binder(AServiceManager_waitForService(service_name));
    hci_ = aidl::android::hardware::bluetooth::IBluetoothHci::fromBinder(binder);
    log::assert_that(hci_ != nullptr, "Failed to retrieve AIDL interface.");

    death_recipient_ =
        ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new([](void* /* cookie*/) {
          log::error("The Bluetooth HAL service died. Dumping logs and crashing in 1 second.");
          common::StopWatch::DumpStopWatchLog();
          // At shutdown, sometimes the HAL service gets killed before Bluetooth.
          std::this_thread::sleep_for(std::chrono::seconds(1));
          log::fatal("The Bluetooth HAL died.");
        }));

    auto death_link = AIBinder_linkToDeath(hci_->asBinder().get(), death_recipient_.get(), this);
    log::assert_that(
        death_link == STATUS_OK, "Unable to set the death recipient for the Bluetooth HAL");
  }

  ~AidlHci() {
    auto death_unlink =
        AIBinder_unlinkToDeath(hci_->asBinder().get(), death_recipient_.get(), this);
    if (death_unlink != STATUS_OK) {
      log::error("Error unlinking death recipient from the Bluetooth HAL");
    }
    auto close_status = hci_->close();
    if (!close_status.isOk()) {
      log::error("Error calling close on the Bluetooth HAL");
    }
  }

  void initialize(std::shared_ptr<HciBackendCallbacks> callbacks) {
    hci_callbacks_ = ::ndk::SharedRefBase::make<AidlHciCallbacks>(callbacks);
    hci_->initialize(hci_callbacks_);
  }

  void sendHciCommand(const std::vector<uint8_t>& command) override {
    hci_->sendHciCommand(command);
  }

  void sendAclData(const std::vector<uint8_t>& packet) override {
    hci_->sendAclData(packet);
  }

  void sendScoData(const std::vector<uint8_t>& packet) override {
    hci_->sendScoData(packet);
  }

  void sendIsoData(const std::vector<uint8_t>& packet) override {
    hci_->sendIsoData(packet);
  }

 private:
  ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
  std::shared_ptr<aidl::android::hardware::bluetooth::IBluetoothHci> hci_;
  std::shared_ptr<AidlHciCallbacks> hci_callbacks_;
};

std::shared_ptr<HciBackend> HciBackend::CreateAidl(const char* service_name) {
  return std::make_shared<AidlHci>(service_name);
}

}  // namespace bluetooth::hal
+181 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#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 <bluetooth/log.h>

#include "common/init_flags.h"
#include "common/stop_watch.h"
#include "common/strings.h"
#include "hal/hci_backend.h"
#include "hal/hci_hal.h"
#include "os/alarm.h"
#include "os/log.h"
#include "os/system_properties.h"

using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using bluetooth::common::BindOnce;
using bluetooth::os::Handler;

using IBluetoothHci_1_0 = ::android::hardware::bluetooth::V1_0::IBluetoothHci;
using IBluetoothHci_1_1 = ::android::hardware::bluetooth::V1_1::IBluetoothHci;
using IBluetoothHciCallbacks_1_1 = ::android::hardware::bluetooth::V1_1::IBluetoothHciCallbacks;

namespace bluetooth::hal {

class HidlHciCallbacks : public IBluetoothHciCallbacks_1_1 {
 public:
  HidlHciCallbacks(std::shared_ptr<HciBackendCallbacks> callbacks) : callbacks_(callbacks) {}

  using HidlStatus = ::android::hardware::bluetooth::V1_0::Status;
  Return<void> initializationComplete(HidlStatus status) override {
    log::assert_that(status == HidlStatus::SUCCESS, "status == HidlStatus::SUCCESS");
    callbacks_->initializationComplete();
    return Void();
  }

  Return<void> hciEventReceived(const hidl_vec<uint8_t>& packet) override {
    callbacks_->hciEventReceived(packet);
    return Void();
  }

  Return<void> aclDataReceived(const hidl_vec<uint8_t>& packet) override {
    callbacks_->aclDataReceived(packet);
    return Void();
  }

  Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) override {
    callbacks_->scoDataReceived(data);
    return Void();
  }

  Return<void> isoDataReceived(const hidl_vec<uint8_t>& data) override {
    callbacks_->isoDataReceived(data);
    return Void();
  }

 private:
  std::shared_ptr<HciBackendCallbacks> callbacks_;
};

class HidlHci : public HciBackend {
  class DeathRecipient : public ::android::hardware::hidl_death_recipient {
   public:
    virtual void serviceDied(
        uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
      log::error("The Bluetooth HAL service died. Dumping logs and crashing in 1 second.");
      common::StopWatch::DumpStopWatchLog();
      // At shutdown, sometimes the HAL service gets killed before Bluetooth.
      std::this_thread::sleep_for(std::chrono::seconds(1));
      log::fatal("The Bluetooth HAL died.");
    }
  };

 public:
  HidlHci(Handler* module_handler) {
    common::StopWatch stop_watch(__func__);
    log::info("Trying to find a HIDL interface");

    auto get_service_alarm = new os::Alarm(module_handler);
    get_service_alarm->Schedule(
        BindOnce([] {
          const std::string kBoardProperty = "ro.product.board";
          const std::string kCuttlefishBoard = "cutf";
          auto board_name = os::GetSystemProperty(kBoardProperty);
          bool emulator = board_name.has_value() && board_name.value() == kCuttlefishBoard;
          if (emulator) {
            log::error("board_name: {}", board_name.value());
            log::error(
                "Unable to get a Bluetooth service after 500ms, start the HAL before starting "
                "Bluetooth");
            return;
          }
          log::fatal(
              "Unable to get a Bluetooth service after 500ms, start the HAL before starting "
              "Bluetooth");
        }),
        std::chrono::milliseconds(500));

    get_service_alarm->Cancel();
    delete get_service_alarm;

    hci_1_1_ = IBluetoothHci_1_1::getService();
    if (hci_1_1_)
      hci_ = hci_1_1_;
    else
      hci_ = IBluetoothHci_1_0::getService();
    log::assert_that(hci_ != nullptr, "assert failed: hci_ != nullptr");

    death_recipient_ = new DeathRecipient();
    auto death_link = hci_->linkToDeath(death_recipient_, 0);
    log::assert_that(death_link.isOk(), "Unable to set the death recipient for the Bluetooth HAL");
  }

  ~HidlHci() {
    log::assert_that(hci_ != nullptr, "assert failed: hci_ != nullptr");
    auto death_unlink = hci_->unlinkToDeath(death_recipient_);
    if (!death_unlink.isOk()) {
      log::error("Error unlinking death recipient from the Bluetooth HAL");
    }
    auto close_status = hci_->close();
    if (!close_status.isOk()) {
      log::error("Error calling close on the Bluetooth HAL");
    }
    hci_ = nullptr;
    hci_1_1_ = nullptr;
  }

  void initialize(std::shared_ptr<HciBackendCallbacks> callbacks) override {
    hci_callbacks_ = new HidlHciCallbacks(callbacks);
    hci_->initialize(hci_callbacks_);
  }

  void sendHciCommand(const std::vector<uint8_t>& command) override {
    hci_->sendHciCommand(command);
  }

  void sendAclData(const std::vector<uint8_t>& packet) override {
    hci_->sendAclData(packet);
  }

  void sendScoData(const std::vector<uint8_t>& packet) override {
    hci_->sendScoData(packet);
  }

  void sendIsoData(const std::vector<uint8_t>& packet) override {
    if (hci_1_1_ == nullptr) {
      log::error("ISO is not supported in HAL v1.0");
      return;
    }
    hci_1_1_->sendIsoData(packet);
  }

 private:
  android::sp<DeathRecipient> death_recipient_;
  android::sp<HidlHciCallbacks> hci_callbacks_;
  android::sp<IBluetoothHci_1_0> hci_;
  android::sp<IBluetoothHci_1_1> hci_1_1_;
};

std::shared_ptr<HciBackend> HciBackend::CreateHidl(Handler* handler) {
  return std::make_shared<HidlHci>(handler);
}

}  // namespace bluetooth::hal
Loading