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

Commit 65f71541 authored by Łukasz Rymanowski (xWF)'s avatar Łukasz Rymanowski (xWF) Committed by Gerrit Code Review
Browse files

Merge changes Id2728761,I91ee7c4a,I78adee24,Idf41311d into main

* changes:
  le_impl_test: Extend direct connection test cases
  le_impl.h: Logs improvement
  le_impl: Add better logs for changing state
  hci_layer_fake: Add debug logs for testing
parents 8342acf3 fb0d6932
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -321,12 +321,18 @@ public:
    }
  }

  void set_connectability_state(ConnectabilityState state) {
    log::debug("{} --> {}", connectability_state_machine_text(connectability_state_),
               connectability_state_machine_text(state));
    connectability_state_ = state;
  }

  // connection canceled by LeAddressManager.OnPause(), will auto reconnect by
  // LeAddressManager.OnResume()
  void on_le_connection_canceled_on_pause() {
    log::assert_that(pause_connection, "Connection must be paused to ack the le address manager");
    arm_on_resume_ = true;
    connectability_state_ = ConnectabilityState::DISARMED;
    set_connectability_state(ConnectabilityState::DISARMED);
    le_address_manager_->AckPause(this);
  }

@@ -394,7 +400,7 @@ public:
    const bool in_filter_accept_list = is_device_in_accept_list(remote_address);

    if (role == hci::Role::CENTRAL) {
      connectability_state_ = ConnectabilityState::DISARMED;
      set_connectability_state(ConnectabilityState::DISARMED);
      if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) {
        on_le_connection_canceled_on_pause();
        return;
@@ -652,9 +658,11 @@ public:
  }

  void direct_connect_add(AddressWithType address_with_type) {
    log::debug("{}", address_with_type);
    direct_connections_.insert(address_with_type);
    if (create_connection_timeout_alarms_.find(address_with_type) !=
        create_connection_timeout_alarms_.end()) {
      log::verbose("Timer already added for {}", address_with_type);
      return;
    }

@@ -672,6 +680,7 @@ public:
  }

  void direct_connect_remove(AddressWithType address_with_type) {
    log::debug("{}", address_with_type);
    auto it = create_connection_timeout_alarms_.find(address_with_type);
    if (it != create_connection_timeout_alarms_.end()) {
      it->second.Cancel();
@@ -691,6 +700,7 @@ public:
      return;
    }

    log::debug("Adding device to accept list {}", address_with_type);
    accept_list.insert(address_with_type);
    register_with_address_manager();
    le_address_manager_->AddDeviceToFilterAcceptList(
@@ -752,8 +762,8 @@ public:
        if (status != ErrorCode::SUCCESS) {
          log::error("Le connection state machine armed failed status:{}", ErrorCodeText(status));
        }
        connectability_state_ = (status == ErrorCode::SUCCESS) ? ConnectabilityState::ARMED
                                                               : ConnectabilityState::DISARMED;
        set_connectability_state((status == ErrorCode::SUCCESS) ? ConnectabilityState::ARMED
                                                                : ConnectabilityState::DISARMED);
        log::info("Le connection state machine armed state:{} status:{}",
                  connectability_state_machine_text(connectability_state_), ErrorCodeText(status));
        if (disarmed_while_arming_) {
@@ -791,7 +801,7 @@ public:
      return;
    }
    AddressWithType empty(Address::kEmpty, AddressType::RANDOM_DEVICE_ADDRESS);
    connectability_state_ = ConnectabilityState::ARMING;
    set_connectability_state(ConnectabilityState::ARMING);
    connecting_le_ = accept_list;

    uint16_t le_scan_interval =
@@ -905,7 +915,7 @@ public:
    switch (connectability_state_) {
      case ConnectabilityState::ARMED:
        log::info("Disarming LE connection state machine with create connection cancel");
        connectability_state_ = ConnectabilityState::DISARMING;
        set_connectability_state(ConnectabilityState::DISARMING);
        le_acl_connection_interface_->EnqueueCommand(
                LeCreateConnectionCancelBuilder::Create(),
                handler_->BindOnce(&le_impl::on_create_connection_cancel_complete,
@@ -964,6 +974,10 @@ public:
      return;
    }

    log::verbose("{}, already_in_accept_list: {}, pause_connection {}, state: {}",
                 address_with_type, already_in_accept_list, pause_connection,
                 connectability_state_machine_text(connectability_state_));

    switch (connectability_state_) {
      case ConnectabilityState::ARMED:
      case ConnectabilityState::ARMING:
+110 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <bluetooth/log.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <log/log.h>

#include <chrono>
#include <future>
@@ -237,6 +238,7 @@ public:
class LeImplTest : public ::testing::Test {
protected:
  void SetUp() override {
    __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
    thread_ = new Thread("thread", Thread::Priority::NORMAL);
    handler_ = new Handler(thread_);
    controller_ = new TestController();
@@ -1422,7 +1424,8 @@ TEST_F(LeImplTest, direct_connection_after_background_connection) {
  hci::AddressWithType address({0x21, 0x22, 0x23, 0x24, 0x25, 0x26},
                               AddressType::PUBLIC_DEVICE_ADDRESS);

  // arrange: Create background connection
  // arrange: Create background connection. Remember that acl_manager adds device background list
  le_impl_->add_device_to_background_connection_list(address);
  le_impl_->create_le_connection(address, true, /* is_direct */ false);
  hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST);
  hci_layer_->IncomingEvent(
@@ -1455,6 +1458,112 @@ TEST_F(LeImplTest, direct_connection_after_background_connection) {
  EXPECT_TRUE(direct_create_connection.IsValid());
  log::info("Scan Interval {}", direct_create_connection.GetLeScanInterval());
  ASSERT_NE(direct_create_connection.GetLeScanInterval(), bg_create_connection.GetLeScanInterval());

  hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
  sync_handler();

  // Check state is ARMED
  ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);

  // Simulate timeout on direct connect. Verify background connect is still in place
  EXPECT_CALL(mock_le_connection_callbacks_,
              OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT))
          .Times(1);
  le_impl_->on_create_connection_timeout(address);
  sync_handler();
  cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
  hci_layer_->IncomingEvent(
          LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
  hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
          ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
          AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
          ClockAccuracy::PPM_30));
  EXPECT_TRUE(cancel_connection.IsValid());
  raw_bg_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
  bg_create_connection = LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
          AclCommandView::Create(raw_bg_create_connection)));
  EXPECT_TRUE(bg_create_connection.IsValid());
  sync_handler();
  ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());

  hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
  sync_handler();

  // Check state is ARMED
  ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
}

TEST_F(LeImplTest, direct_connection_after_direct_connection) {
  set_random_device_address_policy();

  hci::AddressWithType address({0x21, 0x22, 0x23, 0x24, 0x25, 0x26},
                               AddressType::PUBLIC_DEVICE_ADDRESS);

  // Create first direct connection
  le_impl_->create_le_connection(address, true, /* is_direct */ true);
  hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST);
  hci_layer_->IncomingEvent(
          LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
  auto raw_direct_1_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
  hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
  sync_handler();

  // Check state is ARMED
  ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);

  log::info("Second direct connect to the same device");

  // Create second direct connection
  le_impl_->create_le_connection(address, true, /* is_direct */ true);
  sync_handler();

  auto cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
  if (cancel_connection.IsValid()) {
    hci_layer_->IncomingEvent(
            LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
    hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
            ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
            AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
            ClockAccuracy::PPM_30));
  }

  auto raw_direct_2_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);

  // assert
  auto direct_1_create_connection =
          LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
                  AclCommandView::Create(raw_direct_1_create_connection)));
  EXPECT_TRUE(direct_1_create_connection.IsValid());
  auto direct_2_create_connection =
          LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
                  AclCommandView::Create(raw_direct_2_create_connection)));
  EXPECT_TRUE(direct_2_create_connection.IsValid());
  hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
  sync_handler();

  log::info("Simulate timeout");

  EXPECT_CALL(mock_le_connection_callbacks_,
              OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT))
          .Times(1);
  le_impl_->on_create_connection_timeout(address);
  sync_handler();
  cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
  EXPECT_TRUE(cancel_connection.IsValid());
  hci_layer_->IncomingEvent(
          LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
  hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
          ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
          AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
          ClockAccuracy::PPM_30));
  sync_handler();
  ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());

  hci_layer_->GetCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST);
  hci_layer_->IncomingEvent(
          LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
  hci_layer_->AssertNoQueuedCommand();
  ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_);
}

}  // namespace acl_manager
+17 −0
Original line number Diff line number Diff line
@@ -57,11 +57,26 @@ static std::unique_ptr<AclBuilder> NextAclPacket(uint16_t handle) {
  return AclBuilder::Create(handle, packet_boundary_flag, broadcast_flag, NextPayload(handle));
}

static void DebugPrintCommandOpcode(std::string prefix,
                                    const std::unique_ptr<CommandBuilder>& command) {
  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter it(*packet_bytes);
  command->Serialize(it);
  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto temp_cmd_view = CommandView::Create(packet_bytes_view);
  temp_cmd_view.IsValid();
  auto op_code = temp_cmd_view.GetOpCode();

  log::info("{} op_code: {}", prefix, OpCodeText(op_code));
}

void HciLayerFake::EnqueueCommand(
        std::unique_ptr<CommandBuilder> command,
        common::ContextualOnceCallback<void(CommandStatusView)> on_status) {
  std::lock_guard<std::mutex> lock(mutex_);

  DebugPrintCommandOpcode(std::string("Sending with command status, "), command);

  command_queue_.push(std::move(command));
  command_status_callbacks.push_back(std::move(on_status));

@@ -76,6 +91,8 @@ void HciLayerFake::EnqueueCommand(
        common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) {
  std::lock_guard<std::mutex> lock(mutex_);

  DebugPrintCommandOpcode(std::string("Sending with command complete, "), command);

  command_queue_.push(std::move(command));
  command_complete_callbacks.push_back(std::move(on_complete));