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

Commit 9f3ba292 authored by Henri Chataing's avatar Henri Chataing
Browse files

RootCanal: Implement the task scheduler directly in LinkLayerController

Implement a synchronous version of the task scheduler in
LinkLayerController to remove the dependency on an external asynchronous
manager. The callbacks are executed during the tick() invocation.

Test: atest pts-bot:A2DP
Bug: 270203380
Change-Id: I082fd0b63783f8a62d47badb734428aea6be573f
parent 1088ff5f
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
@@ -171,21 +171,6 @@ Return<void> BluetoothHci::initialize_impl(
        });
  }

  controller_->RegisterTaskScheduler(
      [this](std::chrono::milliseconds delay, const TaskCallback& task) {
        return async_manager_.ExecAsync(user_id_, delay, task);
      });

  controller_->RegisterPeriodicTaskScheduler(
      [this](std::chrono::milliseconds delay, std::chrono::milliseconds period,
             const TaskCallback& task) {
        return async_manager_.ExecAsyncPeriodically(user_id_, delay, period,
                                                    task);
      });

  controller_->RegisterTaskCancel(
      [this](AsyncTaskId task) { async_manager_.CancelAsyncTask(task); });

  // Add the controller as a device in the model.
  size_t controller_index = test_model_.AddDevice(controller_);
  size_t low_energy_phy_index =
+5 −5
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ using ::bluetooth::hci::Address;
using ::bluetooth::hci::AddressType;
using ::bluetooth::hci::AddressWithType;

void AclConnectionHandler::Reset(std::function<void(AsyncTaskId)> stopStream) {
void AclConnectionHandler::Reset(std::function<void(TaskId)> stopStream) {
  // Leave no dangling periodic task.
  for (auto& [_, sco_connection] : sco_connections_) {
    sco_connection.StopStream(stopStream);
@@ -158,8 +158,8 @@ uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
  return kReservedHandle;
}

bool AclConnectionHandler::Disconnect(
    uint16_t handle, std::function<void(AsyncTaskId)> stopStream) {
bool AclConnectionHandler::Disconnect(uint16_t handle,
                                      std::function<void(TaskId)> stopStream) {
  if (HasScoHandle(handle)) {
    sco_connections_.at(handle).StopStream(std::move(stopStream));
    sco_connections_.erase(handle);
@@ -515,7 +515,7 @@ void AclConnectionHandler::CancelPendingScoConnection(

bool AclConnectionHandler::AcceptPendingScoConnection(
    bluetooth::hci::Address addr, ScoLinkParameters const& parameters,
    std::function<AsyncTaskId()> startStream) {
    std::function<TaskId()> startStream) {
  for (auto& pair : sco_connections_) {
    if (std::get<ScoConnection>(pair).GetAddress() == addr) {
      std::get<ScoConnection>(pair).SetLinkParameters(parameters);
@@ -529,7 +529,7 @@ bool AclConnectionHandler::AcceptPendingScoConnection(

bool AclConnectionHandler::AcceptPendingScoConnection(
    bluetooth::hci::Address addr, ScoConnectionParameters const& parameters,
    std::function<AsyncTaskId()> startStream) {
    std::function<TaskId()> startStream) {
  for (auto& pair : sco_connections_) {
    if (std::get<ScoConnection>(pair).GetAddress() == addr) {
      bool ok =
+6 −5
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include "hci/address.h"
#include "hci/address_with_type.h"
#include "isochronous_connection_handler.h"
#include "model/setup/async_manager.h"
#include "phy.h"
#include "sco_connection.h"

@@ -37,9 +36,11 @@ class AclConnectionHandler {
  AclConnectionHandler() = default;
  virtual ~AclConnectionHandler() = default;

  using TaskId = uint32_t;

  // Reset the connection manager state, stopping any pending
  // SCO connections.
  void Reset(std::function<void(AsyncTaskId)> stopStream);
  void Reset(std::function<void(TaskId)> stopStream);

  bool CreatePendingConnection(bluetooth::hci::Address addr,
                               bool authenticate_on_connect);
@@ -57,10 +58,10 @@ class AclConnectionHandler {
  void CancelPendingScoConnection(bluetooth::hci::Address addr);
  bool AcceptPendingScoConnection(bluetooth::hci::Address addr,
                                  ScoLinkParameters const& parameters,
                                  std::function<AsyncTaskId()> startStream);
                                  std::function<TaskId()> startStream);
  bool AcceptPendingScoConnection(bluetooth::hci::Address addr,
                                  ScoConnectionParameters const& parameters,
                                  std::function<AsyncTaskId()> startStream);
                                  std::function<TaskId()> startStream);
  uint16_t GetScoHandle(bluetooth::hci::Address addr) const;
  ScoConnectionParameters GetScoConnectionParameters(
      bluetooth::hci::Address addr) const;
@@ -77,7 +78,7 @@ class AclConnectionHandler {
  uint16_t CreateLeConnection(bluetooth::hci::AddressWithType addr,
                              bluetooth::hci::AddressWithType own_addr,
                              bluetooth::hci::Role role);
  bool Disconnect(uint16_t handle, std::function<void(AsyncTaskId)> stopStream);
  bool Disconnect(uint16_t handle, std::function<void(TaskId)> stopStream);
  bool HasHandle(uint16_t handle) const;
  bool HasScoHandle(uint16_t handle) const;

+0 −52
Original line number Diff line number Diff line
@@ -95,58 +95,6 @@ void DualModeController::SniffSubrating(CommandView command) {
      command_view.GetConnectionHandle()));
}

void DualModeController::RegisterTaskScheduler(
    std::function<AsyncTaskId(std::chrono::milliseconds, TaskCallback)>
        task_scheduler) {
  link_layer_controller_.RegisterTaskScheduler(
      [this, schedule = std::move(task_scheduler)](
          std::chrono::milliseconds delay_ms, TaskCallback callback) {
        // weak_from_this is valid only if [this] is already protected
        // behind a shared_ptr; this is the case in TestModel.
        return schedule(delay_ms, [lifetime = weak_from_this(),
                                   callback = std::move(callback)] {
          // Capture a weak_ptr of the DualModeController object to protect
          // against the execution of callbacks capturing dead pointers.
          // This can occur if the device is deleted with scheduled events.
          if (lifetime.lock() != nullptr) {
            callback();
          }
        });
      });
}

void DualModeController::RegisterPeriodicTaskScheduler(
    std::function<AsyncTaskId(std::chrono::milliseconds,
                              std::chrono::milliseconds, TaskCallback)>
        periodic_task_scheduler) {
  link_layer_controller_.RegisterPeriodicTaskScheduler(
      [this, schedule = std::move(periodic_task_scheduler)](
          std::chrono::milliseconds delay_ms,
          std::chrono::milliseconds interval_ms, TaskCallback callback) {
        // weak_from_this is valid only if [this] is already protected
        // behind a shared_ptr; this is the case in TestModel.
        return schedule(
            delay_ms, interval_ms,
            [lifetime = weak_from_this(), callback = std::move(callback)] {
              // Capture a weak_ptr of the DualModeController object to protect
              // against the execution of callbacks capturing dead pointers.
              // This can occur if the device is deleted with scheduled events.
              //
              // Note: the task handle cannot be cancelled from this context;
              // we depend on the link layer to properly clean-up pending
              // periodic tasks when deleted.
              if (lifetime.lock() != nullptr) {
                callback();
              }
            });
      });
}

void DualModeController::RegisterTaskCancel(
    std::function<void(AsyncTaskId)> task_cancel) {
  link_layer_controller_.RegisterTaskCancel(task_cancel);
}

void DualModeController::HandleAcl(
    std::shared_ptr<std::vector<uint8_t>> packet) {
  bluetooth::hci::PacketView<bluetooth::hci::kLittleEndian> raw_packet(packet);
+1 −16
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#include "link_layer_controller.h"
#include "model/controller/vendor_commands/csr.h"
#include "model/devices/device.h"
#include "model/setup/async_manager.h"
#ifndef ROOTCANAL_LMP
#include "security_manager.h"
#endif /* !ROOTCANAL_LMP */
@@ -51,9 +50,7 @@ using ::bluetooth::hci::CommandView;
// the controller's default constructor. Be sure to name your method after the
// corresponding Bluetooth command in the Core Specification with the prefix
// "Hci" to distinguish it as a controller command.
class DualModeController
    : public Device,
      public std::enable_shared_from_this<DualModeController> {
class DualModeController : public Device {
  static constexpr uint16_t kSecurityManagerNumKeys = 15;

 public:
@@ -79,18 +76,6 @@ class DualModeController
  void HandleSco(std::shared_ptr<std::vector<uint8_t>> sco_packet);
  void HandleIso(std::shared_ptr<std::vector<uint8_t>> iso_packet);

  // Set the callbacks for scheduling tasks.
  void RegisterTaskScheduler(
      std::function<AsyncTaskId(std::chrono::milliseconds, TaskCallback)>
          task_scheduler);

  void RegisterPeriodicTaskScheduler(
      std::function<AsyncTaskId(std::chrono::milliseconds,
                                std::chrono::milliseconds, TaskCallback)>
          periodic_task_scheduler);

  void RegisterTaskCancel(std::function<void(AsyncTaskId)> cancel);

  // Set the callbacks for sending packets to the HCI.
  void RegisterEventChannel(
      const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>&
Loading