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

Commit 27ba142f authored by Myles Watson's avatar Myles Watson Committed by android-build-merger
Browse files

HCI: Add LE support to AclManager am: ffd40b7b

am: a0ea1d0a

Change-Id: Ib4bf0ae32107b8bb58138193e064e58992f33866
parents 1b680f8d a0ea1d0a
Loading
Loading
Loading
Loading
+121 −19
Original line number Diff line number Diff line
@@ -71,6 +71,11 @@ struct AclManager::impl {
                                     Bind(&impl::on_disconnection_complete, common::Unretained(this)), handler_);
    hci_layer_->RegisterEventHandler(EventCode::CONNECTION_REQUEST,
                                     Bind(&impl::on_incoming_connection, common::Unretained(this)), handler_);
    hci_layer_->RegisterLeEventHandler(SubeventCode::CONNECTION_COMPLETE,
                                       Bind(&impl::on_le_connection_complete, common::Unretained(this)), handler_);
    hci_layer_->RegisterLeEventHandler(SubeventCode::ENHANCED_CONNECTION_COMPLETE,
                                       Bind(&impl::on_le_enhanced_connection_complete, common::Unretained(this)),
                                       handler_);
  }

  void Stop() {
@@ -220,18 +225,27 @@ struct AclManager::impl {
    }
  }

  void on_connection_complete(EventPacketView packet) {
    ConnectionCompleteView connection_complete = ConnectionCompleteView::Create(std::move(packet));
    ASSERT(connection_complete.IsValid());
    auto status = connection_complete.GetStatus();
    auto address = connection_complete.GetBdAddr();
  void on_any_connection_complete(Address address) {
    auto connecting_addr = connecting_.find(address);
    if (connecting_addr == connecting_.end()) {
      LOG_WARN("No prior connection request for %s", address.ToString().c_str());
    } else {
      connecting_.erase(connecting_addr);
    }
    if (status == ErrorCode::SUCCESS) {
  }

  void on_le_connection_complete(LeMetaEventView packet) {
    LeConnectionCompleteView connection_complete = LeConnectionCompleteView::Create(packet);
    ASSERT(connection_complete.IsValid());
    auto status = connection_complete.GetStatus();
    auto address = connection_complete.GetPeerAddress();
    on_any_connection_complete(address);
    if (status != ErrorCode::SUCCESS) {
      client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectFail, common::Unretained(client_callbacks_),
                                             address, status));
      return;
    }
    // TODO: Check and save other connection parameters
    uint16_t handle = connection_complete.GetConnectionHandle();
    ASSERT(acl_connections_.count(handle) == 0);
    acl_connections_[handle] = {};
@@ -241,14 +255,55 @@ struct AclManager::impl {
    std::unique_ptr<AclConnection> connection_proxy(new AclConnection(&acl_manager_, handle, address));
    client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectSuccess,
                                           common::Unretained(client_callbacks_), std::move(connection_proxy)));
    } else {
  }

  void on_le_enhanced_connection_complete(LeMetaEventView packet) {
    LeEnhancedConnectionCompleteView connection_complete = LeEnhancedConnectionCompleteView::Create(packet);
    ASSERT(connection_complete.IsValid());
    auto status = connection_complete.GetStatus();
    auto address = connection_complete.GetPeerAddress();
    on_any_connection_complete(address);
    if (status != ErrorCode::SUCCESS) {
      client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectFail, common::Unretained(client_callbacks_),
                                             address, status));
      return;
    }
    // TODO: Check and save other connection parameters
    uint16_t handle = connection_complete.GetConnectionHandle();
    ASSERT(acl_connections_.count(handle) == 0);
    acl_connections_[handle] = {};
    if (acl_connections_.size() == 1 && packet_to_send_ == nullptr) {
      start_round_robin();
    }
    std::unique_ptr<AclConnection> connection_proxy(new AclConnection(&acl_manager_, handle, address));
    client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectSuccess,
                                           common::Unretained(client_callbacks_), std::move(connection_proxy)));
  }

  void on_connection_complete(EventPacketView packet) {
    ConnectionCompleteView connection_complete = ConnectionCompleteView::Create(packet);
    ASSERT(connection_complete.IsValid());
    auto status = connection_complete.GetStatus();
    auto address = connection_complete.GetBdAddr();
    on_any_connection_complete(address);
    if (status != ErrorCode::SUCCESS) {
      client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectFail, common::Unretained(client_callbacks_),
                                             address, status));
      return;
    }
    uint16_t handle = connection_complete.GetConnectionHandle();
    ASSERT(acl_connections_.count(handle) == 0);
    acl_connections_[handle] = {};
    if (acl_connections_.size() == 1 && packet_to_send_ == nullptr) {
      start_round_robin();
    }
    std::unique_ptr<AclConnection> connection_proxy(new AclConnection(&acl_manager_, handle, address));
    client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectSuccess,
                                           common::Unretained(client_callbacks_), std::move(connection_proxy)));
  }

  void on_disconnection_complete(EventPacketView packet) {
    DisconnectionCompleteView disconnection_complete = DisconnectionCompleteView::Create(std::move(packet));
    DisconnectionCompleteView disconnection_complete = DisconnectionCompleteView::Create(packet);
    ASSERT(disconnection_complete.IsValid());
    uint16_t handle = disconnection_complete.GetConnectionHandle();
    auto status = disconnection_complete.GetStatus();
@@ -287,6 +342,34 @@ struct AclManager::impl {
                               handler_);
  }

  void create_le_connection(Address address, AddressType address_type) {
    // TODO: Add white list handling.
    // TODO: Configure default LE connection parameters?
    uint16_t le_scan_interval = 0x0020;
    uint16_t le_scan_window = 0x0010;
    InitiatorFilterPolicy initiator_filter_policy = InitiatorFilterPolicy::USE_PEER_ADDRESS;
    OwnAddressType own_address_type = OwnAddressType::RANDOM_DEVICE_ADDRESS;
    uint16_t conn_interval_min = 0x0006;
    uint16_t conn_interval_max = 0x0C00;
    uint16_t conn_latency = 0x0C0;
    uint16_t supervision_timeout = 0x0C00;
    uint16_t minimum_ce_length = 0x0002;
    uint16_t maximum_ce_length = 0x0C00;
    ASSERT(le_client_callbacks_ != nullptr);

    connecting_.insert(address);

    hci_layer_->EnqueueCommand(
        LeCreateConnectionBuilder::Create(le_scan_interval, le_scan_window, initiator_filter_policy, address_type,
                                          address, own_address_type, conn_interval_min, conn_interval_max, conn_latency,
                                          supervision_timeout, minimum_ce_length, maximum_ce_length),
        common::BindOnce([](CommandStatusView status) {
          ASSERT(status.IsValid());
          ASSERT(status.GetCommandOpCode() == OpCode::CREATE_CONNECTION);
        }),
        handler_);
  }

  void cancel_connect(Address address) {
    auto connecting_addr = connecting_.find(address);
    if (connecting_addr == connecting_.end()) {
@@ -343,6 +426,13 @@ struct AclManager::impl {
    client_handler_ = handler;
  }

  void handle_register_le_callbacks(LeConnectionCallbacks* callbacks, os::Handler* handler) {
    ASSERT(le_client_callbacks_ == nullptr);
    ASSERT(le_client_handler_ == nullptr);
    le_client_callbacks_ = callbacks;
    le_client_handler_ = handler;
  }

  acl_connection& check_and_get_connection(uint16_t handle) {
    auto connection = acl_connections_.find(handle);
    ASSERT(connection != acl_connections_.end());
@@ -396,6 +486,8 @@ struct AclManager::impl {
  os::Handler* handler_ = nullptr;
  ConnectionCallbacks* client_callbacks_ = nullptr;
  os::Handler* client_handler_ = nullptr;
  LeConnectionCallbacks* le_client_callbacks_ = nullptr;
  os::Handler* le_client_handler_ = nullptr;
  common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* hci_queue_end_ = nullptr;
  std::map<uint16_t, AclManager::acl_connection> acl_connections_;
  std::set<Address> connecting_;
@@ -421,17 +513,27 @@ void AclConnection::Finish() {

AclManager::AclManager() : pimpl_(std::make_unique<impl>(*this)) {}

bool AclManager::RegisterCallbacks(ConnectionCallbacks* callbacks, os::Handler* handler) {
void AclManager::RegisterCallbacks(ConnectionCallbacks* callbacks, os::Handler* handler) {
  ASSERT(callbacks != nullptr && handler != nullptr);
  GetHandler()->Post(common::BindOnce(&impl::handle_register_callbacks, common::Unretained(pimpl_.get()),
                                      common::Unretained(callbacks), common::Unretained(handler)));
  return true;
}

void AclManager::RegisterLeCallbacks(LeConnectionCallbacks* callbacks, os::Handler* handler) {
  ASSERT(callbacks != nullptr && handler != nullptr);
  GetHandler()->Post(common::BindOnce(&impl::handle_register_le_callbacks, common::Unretained(pimpl_.get()),
                                      common::Unretained(callbacks), common::Unretained(handler)));
}

void AclManager::CreateConnection(Address address) {
  GetHandler()->Post(common::BindOnce(&impl::create_connection, common::Unretained(pimpl_.get()), address));
}

void AclManager::CreateLeConnection(Address address, AddressType address_type) {
  GetHandler()->Post(
      common::BindOnce(&impl::create_le_connection, common::Unretained(pimpl_.get()), address, address_type));
}

void AclManager::CancelConnect(Address address) {
  GetHandler()->Post(BindOnce(&impl::cancel_connect, common::Unretained(pimpl_.get()), address));
}
+17 −2
Original line number Diff line number Diff line
@@ -74,6 +74,15 @@ class ConnectionCallbacks {
  virtual void OnConnectFail(Address, ErrorCode reason) = 0;
};

class LeConnectionCallbacks {
 public:
  virtual ~LeConnectionCallbacks() = default;
  // Invoked when controller sends Connection Complete event with Success error code
  virtual void OnLeConnectSuccess(std::unique_ptr<AclConnection> /* , initiated_by_local ? */) = 0;
  // Invoked when controller sends Connection Complete event with non-Success error code
  virtual void OnLeConnectFail(Address, AddressType, ErrorCode reason) = 0;
};

class AclManager : public Module {
 public:
  AclManager();
@@ -83,13 +92,19 @@ class AclManager : public Module {
  // compiling AclManager's destructor until it starts linking the .cc file.
  ~AclManager() override;

  // Returns true if callbacks are successfully registered. Should register only once when user module starts.
  // Should register only once when user module starts.
  // Generates OnConnectSuccess when an incoming connection is established.
  virtual bool RegisterCallbacks(ConnectionCallbacks* callbacks, os::Handler* handler);
  virtual void RegisterCallbacks(ConnectionCallbacks* callbacks, os::Handler* handler);

  // Should register only once when user module starts.
  virtual void RegisterLeCallbacks(LeConnectionCallbacks* callbacks, os::Handler* handler);

  // Generates OnConnectSuccess if connected, or OnConnectFail otherwise
  virtual void CreateConnection(Address address);

  // Generates OnLeConnectSuccess if connected, or OnLeConnectFail otherwise
  virtual void CreateLeConnection(Address address, AddressType address_type);

  // Generates OnConnectFail with error code "terminated by local host 0x16" if cancelled, or OnConnectSuccess if not
  // successfully cancelled and already connected
  virtual void CancelConnect(Address address);
+2 −1
Original line number Diff line number Diff line
@@ -36,8 +36,9 @@ class MockAclConnection : public AclConnection {

class MockAclManager : public AclManager {
 public:
  MOCK_METHOD(bool, RegisterCallbacks, (ConnectionCallbacks * callbacks, os::Handler* handler), (override));
  MOCK_METHOD(void, RegisterCallbacks, (ConnectionCallbacks * callbacks, os::Handler* handler), (override));
  MOCK_METHOD(void, CreateConnection, (Address address), (override));
  MOCK_METHOD(void, CreateLeConnection, (Address address, AddressType address_type), (override));
  MOCK_METHOD(void, CancelConnect, (Address address), (override));
};

+3 −3
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl) {
  hci::ConnectionCallbacks* hci_connection_callbacks = nullptr;
  os::Handler* hci_callback_handler = nullptr;
  EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _))
      .WillOnce(DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler), Return(true)));
      .WillOnce(DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler)));
  ClassicLinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager,
                                          &mock_classic_fixed_channel_service_manager);
  EXPECT_EQ(hci_connection_callbacks, &classic_link_manager);
@@ -159,7 +159,7 @@ TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl_wi
  hci::ConnectionCallbacks* hci_connection_callbacks = nullptr;
  os::Handler* hci_callback_handler = nullptr;
  EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _))
      .WillOnce(DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler), Return(true)));
      .WillOnce(DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler)));
  ClassicLinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager,
                                          &mock_classic_fixed_channel_service_manager);
  EXPECT_EQ(hci_connection_callbacks, &classic_link_manager);
@@ -194,7 +194,7 @@ TEST_F(L2capClassicLinkManagerTest, connect_fixed_channel_service_without_acl_wi
  hci::ConnectionCallbacks* hci_connection_callbacks = nullptr;
  os::Handler* hci_callback_handler = nullptr;
  EXPECT_CALL(mock_acl_manager, RegisterCallbacks(_, _))
      .WillOnce(DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler), Return(true)));
      .WillOnce(DoAll(SaveArg<0>(&hci_connection_callbacks), SaveArg<1>(&hci_callback_handler)));
  ClassicLinkManager classic_link_manager(l2cap_handler_, &mock_acl_manager,
                                          &mock_classic_fixed_channel_service_manager);
  EXPECT_EQ(hci_connection_callbacks, &classic_link_manager);