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

Commit 60aa80c2 authored by Chienyuan's avatar Chienyuan
Browse files

gd HCI: LE White list management

Tag: #gd-refactor
Bug: 152346341
Test: gd/cert/run --host
Test: atest bluetooth_test_gd
Change-Id: Ie437b1bed4dad187024d5325499cca791d15052d
parent 65fd4f98
Loading
Loading
Loading
Loading
+7 −21
Original line number Diff line number Diff line
@@ -53,9 +53,11 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
    le_acl_connection_interface_ = hci_layer_->GetLeAclConnectionInterface(
        handler_->BindOn(this, &le_impl::on_le_event), handler_->BindOn(this, &le_impl::on_le_disconnect));
    le_address_manager_ = new LeAddressManager(
        common::Bind(&le_impl::SetRandomAddress, common::Unretained(this)),
        common::Bind(&le_impl::enqueue_command, common::Unretained(this)),
        handler_,
        controller->GetControllerMacAddress());
        controller->GetControllerMacAddress(),
        controller->GetControllerLeWhiteListSize(),
        controller->GetControllerLeResolvingListSize());
  }

  ~le_impl() {
@@ -216,26 +218,10 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
        complete_view.GetConnInterval(), complete_view.GetConnLatency(), complete_view.GetSupervisionTimeout());
  }

  void on_le_set_random_address_complete(CommandCompleteView view) {
    auto complete_view = LeSetRandomAddressCompleteView::Create(view);
    if (!complete_view.IsValid()) {
      LOG_ERROR("Received on_le_set_random_address_complete with invalid packet");
      le_address_manager_->OnLeSetRandomAddressComplete(false);
      return;
    } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      auto status = complete_view.GetStatus();
      std::string error_code = ErrorCodeText(status);
      LOG_ERROR("Received on_le_set_random_address_complete with error code %s", error_code.c_str());
      le_address_manager_->OnLeSetRandomAddressComplete(false);
      return;
    }
    le_address_manager_->OnLeSetRandomAddressComplete(true);
  }

  void SetRandomAddress(Address address) {
  void enqueue_command(std::unique_ptr<CommandPacketBuilder> command_packet) {
    hci_layer_->EnqueueCommand(
        hci::LeSetRandomAddressBuilder::Create(address),
        handler_->BindOnce(&le_impl::on_le_set_random_address_complete, common::Unretained(this)));
        std::move(command_packet),
        handler_->BindOnce(&LeAddressManager::OnCommandComplete, common::Unretained(le_address_manager_)));
  }

  void create_le_connection(AddressWithType address_with_type) {
+34 −0
Original line number Diff line number Diff line
@@ -66,6 +66,14 @@ struct Controller::impl {
    hci_->EnqueueCommand(LeReadSupportedStatesBuilder::Create(),
                         handler->BindOnceOn(this, &Controller::impl::le_read_supported_states_handler));

    hci_->EnqueueCommand(
        LeReadWhiteListSizeBuilder::Create(),
        handler->BindOnceOn(this, &Controller::impl::le_read_white_list_size_handler));

    hci_->EnqueueCommand(
        LeReadResolvingListSizeBuilder::Create(),
        handler->BindOnceOn(this, &Controller::impl::le_read_resolving_list_size_handler));

    if (is_supported(OpCode::LE_READ_MAXIMUM_DATA_LENGTH)) {
      hci_->EnqueueCommand(LeReadMaximumDataLengthBuilder::Create(),
                           handler->BindOnceOn(this, &Controller::impl::le_read_maximum_data_length_handler));
@@ -233,6 +241,22 @@ struct Controller::impl {
    le_supported_states_ = complete_view.GetLeStates();
  }

  void le_read_white_list_size_handler(CommandCompleteView view) {
    auto complete_view = LeReadWhiteListSizeCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
    ErrorCode status = complete_view.GetStatus();
    ASSERT_LOG(status == ErrorCode::SUCCESS, "Status 0x%02hhx, %s", status, ErrorCodeText(status).c_str());
    le_white_list_size_ = complete_view.GetWhiteListSize();
  }

  void le_read_resolving_list_size_handler(CommandCompleteView view) {
    auto complete_view = LeReadResolvingListSizeCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
    ErrorCode status = complete_view.GetStatus();
    ASSERT_LOG(status == ErrorCode::SUCCESS, "Status 0x%02hhx, %s", status, ErrorCodeText(status).c_str());
    le_resolving_list_size_ = complete_view.GetResolvingListSize();
  }

  void le_read_maximum_data_length_handler(CommandCompleteView view) {
    auto complete_view = LeReadMaximumDataLengthCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
@@ -695,6 +719,8 @@ struct Controller::impl {
  LeBufferSize le_buffer_size_;
  uint64_t le_local_supported_features_;
  uint64_t le_supported_states_;
  uint8_t le_white_list_size_;
  uint8_t le_resolving_list_size_;
  LeMaximumDataLength le_maximum_data_length_;
  uint16_t le_maximum_advertising_data_length_;
  uint8_t le_number_supported_advertising_sets_;
@@ -846,6 +872,14 @@ uint64_t Controller::GetControllerLeSupportedStates() const {
  return impl_->le_supported_states_;
}

uint8_t Controller::GetControllerLeWhiteListSize() const {
  return impl_->le_white_list_size_;
}

uint8_t Controller::GetControllerLeResolvingListSize() const {
  return impl_->le_resolving_list_size_;
}

LeMaximumDataLength Controller::GetControllerLeMaximumDataLength() const {
  return impl_->le_maximum_data_length_;
}
+4 −0
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ class Controller : public Module {

  virtual uint64_t GetControllerLeSupportedStates() const;

  virtual uint8_t GetControllerLeWhiteListSize() const;

  virtual uint8_t GetControllerLeResolvingListSize() const;

  virtual LeMaximumDataLength GetControllerLeMaximumDataLength() const;

  virtual uint16_t GetControllerLeMaximumAdvertisingDataLength() const;
+3 −2
Original line number Diff line number Diff line
@@ -2583,7 +2583,7 @@ packet LeCreateConnectionCancelComplete : CommandComplete (command_op_code = LE_
  status : ErrorCode,
}

packet LeReadWhiteListSize : LeConnectionManagementCommand (op_code = LE_READ_WHITE_LIST_SIZE) {
packet LeReadWhiteListSize : CommandPacket (op_code = LE_READ_WHITE_LIST_SIZE) {
}

packet LeReadWhiteListSizeComplete : CommandComplete (command_op_code = LE_READ_WHITE_LIST_SIZE) {
@@ -2826,11 +2826,12 @@ packet LeClearResolvingListComplete : CommandComplete (command_op_code = LE_CLEA
  status : ErrorCode,
}

packet LeReadResolvingListSize : LeSecurityCommand (op_code = LE_READ_RESOLVING_LIST_SIZE) {
packet LeReadResolvingListSize : CommandPacket (op_code = LE_READ_RESOLVING_LIST_SIZE) {
}

packet LeReadResolvingListSizeComplete : CommandComplete (command_op_code = LE_READ_RESOLVING_LIST_SIZE) {
  status : ErrorCode,
  resolving_list_size : 8,
}

packet LeReadPeerResolvableAddress : LeSecurityCommand (op_code = LE_READ_PEER_RESOLVABLE_ADDRESS) {
+135 −16
Original line number Diff line number Diff line
@@ -8,8 +8,16 @@ namespace hci {
static constexpr uint8_t BLE_ADDR_MASK = 0xc0u;

LeAddressManager::LeAddressManager(
    common::Callback<void(Address address)> set_random_address, os::Handler* handler, Address public_address)
    : set_random_address_(set_random_address), handler_(handler), public_address_(public_address){};
    common::Callback<void(std::unique_ptr<CommandPacketBuilder>)> enqueue_command,
    os::Handler* handler,
    Address public_address,
    uint8_t white_list_size,
    uint8_t resolving_list_size)
    : enqueue_command_(enqueue_command),
      handler_(handler),
      public_address_(public_address),
      white_list_size_(white_list_size),
      resolving_list_size_(resolving_list_size){};

LeAddressManager::~LeAddressManager() {
  if (address_rotation_alarm_ != nullptr) {
@@ -47,7 +55,8 @@ void LeAddressManager::SetPrivacyPolicyForInitiatorAddress(
        LOG_ALWAYS_FATAL("Bits of the random part of the address shall not be all 1 or all 0");
      }
      le_address_ = fixed_address;
      handler_->Post(common::Bind(set_random_address_, le_address_.GetAddress()));
      auto packet = hci::LeSetRandomAddressBuilder::Create(le_address_.GetAddress());
      handler_->Post(common::BindOnce(enqueue_command_, std::move(packet)));
    } break;
    case AddressPolicy::USE_NON_RESOLVABLE_ADDRESS:
    case AddressPolicy::USE_RESOLVABLE_ADDRESS:
@@ -62,7 +71,7 @@ void LeAddressManager::SetPrivacyPolicyForInitiatorAddress(
}

LeAddressManager::AddressPolicy LeAddressManager::Register(LeAddressManagerCallback* callback) {
  handler_->Post(common::BindOnce(&LeAddressManager::register_client, common::Unretained(this), callback));
  handler_->BindOnceOn(this, &LeAddressManager::register_client, callback).Invoke();
  return address_policy_;
}

@@ -70,12 +79,12 @@ void LeAddressManager::register_client(LeAddressManagerCallback* callback) {
  registered_clients_.insert(std::pair<LeAddressManagerCallback*, ClientState>(callback, ClientState::RESUMED));
  if (address_policy_ == AddressPolicy::POLICY_NOT_SET || address_policy_ == AddressPolicy::USE_RESOLVABLE_ADDRESS ||
      address_policy_ == AddressPolicy::USE_NON_RESOLVABLE_ADDRESS) {
    pause_registered_clients();
    prepare_to_rotate();
  }
}

void LeAddressManager::Unregister(LeAddressManagerCallback* callback) {
  handler_->Post(common::BindOnce(&LeAddressManager::unregister_client, common::Unretained(this), callback));
  handler_->BindOnceOn(this, &LeAddressManager::unregister_client, callback).Invoke();
}

void LeAddressManager::unregister_client(LeAddressManagerCallback* callback) {
@@ -87,16 +96,11 @@ void LeAddressManager::unregister_client(LeAddressManagerCallback* callback) {
}

void LeAddressManager::AckPause(LeAddressManagerCallback* callback) {
  handler_->Post(common::BindOnce(&LeAddressManager::ack_pause, common::Unretained(this), callback));
  handler_->BindOnceOn(this, &LeAddressManager::ack_pause, callback).Invoke();
}

void LeAddressManager::AckResume(LeAddressManagerCallback* callback) {
  handler_->Post(common::BindOnce(&LeAddressManager::ack_resume, common::Unretained(this), callback));
}

void LeAddressManager::OnLeSetRandomAddressComplete(bool success) {
  ASSERT(success);
  resume_registered_clients();
  handler_->BindOnceOn(this, &LeAddressManager::ack_resume, callback).Invoke();
}

AddressWithType LeAddressManager::GetCurrentAddress() {
@@ -131,10 +135,16 @@ void LeAddressManager::ack_pause(LeAddressManagerCallback* callback) {
      return;
    }
  }
  rotate_random_address();
  handle_next_command();
}

void LeAddressManager::resume_registered_clients() {
  // Do not resume clients if cached command is not empty
  if (!cached_commands_.empty()) {
    handle_next_command();
    return;
  }

  for (auto client : registered_clients_) {
    client.second = ClientState::WAITING_FOR_RESUME;
    client.first->OnResume();
@@ -146,6 +156,12 @@ void LeAddressManager::ack_resume(LeAddressManagerCallback* callback) {
  registered_clients_.find(callback)->second = ClientState::RESUMED;
}

void LeAddressManager::prepare_to_rotate() {
  Command command = {CommandType::ROTATE_RANDOM_ADDRESS, nullptr};
  cached_commands_.push(std::move(command));
  pause_registered_clients();
}

void LeAddressManager::rotate_random_address() {
  if (address_policy_ != AddressPolicy::USE_RESOLVABLE_ADDRESS &&
      address_policy_ != AddressPolicy::USE_NON_RESOLVABLE_ADDRESS) {
@@ -153,7 +169,7 @@ void LeAddressManager::rotate_random_address() {
  }

  address_rotation_alarm_->Schedule(
      common::BindOnce(&LeAddressManager::pause_registered_clients, common::Unretained(this)),
      common::BindOnce(&LeAddressManager::prepare_to_rotate, common::Unretained(this)),
      get_next_private_address_interval_ms());

  hci::Address address;
@@ -162,10 +178,27 @@ void LeAddressManager::rotate_random_address() {
  } else {
    address = generate_nrpa();
  }
  handler_->Post(common::Bind(set_random_address_, address));
  auto packet = hci::LeSetRandomAddressBuilder::Create(address);
  enqueue_command_.Run(std::move(packet));
  le_address_ = AddressWithType(address, AddressType::RANDOM_DEVICE_ADDRESS);
}

void LeAddressManager::on_le_set_random_address_complete(CommandCompleteView view) {
  auto complete_view = LeSetRandomAddressCompleteView::Create(view);
  if (!complete_view.IsValid()) {
    LOG_ALWAYS_FATAL("Received on_le_set_random_address_complete with invalid packet");
  } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
    auto status = complete_view.GetStatus();
    std::string error_code = ErrorCodeText(status);
    LOG_ALWAYS_FATAL("Received on_le_set_random_address_complete with error code %s", error_code.c_str());
  }
  if (cached_commands_.empty()) {
    handler_->BindOnceOn(this, &LeAddressManager::resume_registered_clients).Invoke();
  } else {
    handler_->BindOnceOn(this, &LeAddressManager::handle_next_command).Invoke();
  }
}

/* This function generates Resolvable Private Address (RPA) from Identity
 * Resolving Key |irk| and |prand|*/
hci::Address LeAddressManager::generate_rpa() {
@@ -225,5 +258,91 @@ std::chrono::milliseconds LeAddressManager::get_next_private_address_interval_ms
  return minimum_rotation_time_ + random_ms;
}

uint8_t LeAddressManager::GetWhiteListSize() {
  return white_list_size_;
}

uint8_t LeAddressManager::GetResolvingListSize() {
  return resolving_list_size_;
}

void LeAddressManager::handle_next_command() {
  ASSERT(!cached_commands_.empty());
  auto command = std::move(cached_commands_.front());
  cached_commands_.pop();

  if (command.command_type == CommandType::ROTATE_RANDOM_ADDRESS) {
    rotate_random_address();
  } else {
    enqueue_command_.Run(std::move(command.command_packet));
  }
}

void LeAddressManager::AddDeviceToWhiteList(
    WhiteListAddressType white_list_address_type, bluetooth::hci::Address address) {
  auto packet_builder = hci::LeAddDeviceToWhiteListBuilder::Create(white_list_address_type, address);
  Command command = {CommandType::ADD_DEVICE_TO_WHITE_LIST, std::move(packet_builder)};
  handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke();
  cached_commands_.push(std::move(command));
}

void LeAddressManager::AddDeviceToResolvingList(
    PeerAddressType peer_identity_address_type,
    Address peer_identity_address,
    const std::array<uint8_t, 16>& peer_irk,
    const std::array<uint8_t, 16>& local_irk) {
  auto packet_builder = hci::LeAddDeviceToResolvingListBuilder::Create(
      peer_identity_address_type, peer_identity_address, peer_irk, local_irk);
  Command command = {CommandType::ADD_DEVICE_TO_RESOLVING_LIST, std::move(packet_builder)};
  handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke();
  cached_commands_.push(std::move(command));
}

void LeAddressManager::RemoveDeviceFromWhiteList(
    WhiteListAddressType white_list_address_type, bluetooth::hci::Address address) {
  auto packet_builder = hci::LeRemoveDeviceFromWhiteListBuilder::Create(white_list_address_type, address);
  Command command = {CommandType::REMOVE_DEVICE_FROM_WHITE_LIST, std::move(packet_builder)};
  handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke();
  cached_commands_.push(std::move(command));
}

void LeAddressManager::RemoveDeviceFromResolvingList(
    PeerAddressType peer_identity_address_type, Address peer_identity_address) {
  auto packet_builder =
      hci::LeRemoveDeviceFromResolvingListBuilder::Create(peer_identity_address_type, peer_identity_address);
  Command command = {CommandType::REMOVE_DEVICE_FROM_RESOLVING_LIST, std::move(packet_builder)};
  handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke();
  cached_commands_.push(std::move(command));
}

void LeAddressManager::ClearWhiteList() {
  auto packet_builder = hci::LeClearWhiteListBuilder::Create();
  Command command = {CommandType::CLEAR_WHITE_LIST, std::move(packet_builder)};
  handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke();
  cached_commands_.push(std::move(command));
}

void LeAddressManager::ClearResolvingList() {
  auto packet_builder = hci::LeClearResolvingListBuilder::Create();
  Command command = {CommandType::CLEAR_RESOLVING_LIST, std::move(packet_builder)};
  handler_->BindOnceOn(this, &LeAddressManager::pause_registered_clients).Invoke();
  cached_commands_.push(std::move(command));
}

void LeAddressManager::OnCommandComplete(bluetooth::hci::CommandCompleteView view) {
  if (!view.IsValid()) {
    LOG_ERROR("Received command complete with invalid packet");
    return;
  }
  std::string op_code = OpCodeText(view.GetCommandOpCode());
  LOG_ERROR("Received command complete with op_code %s", op_code.c_str());

  if (cached_commands_.empty()) {
    handler_->BindOnceOn(this, &LeAddressManager::resume_registered_clients).Invoke();
  } else {
    handler_->BindOnceOn(this, &LeAddressManager::handle_next_command).Invoke();
  }
}

}  // namespace hci
}  // namespace bluetooth
Loading