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

Commit 5408d096 authored by Chienyuan's avatar Chienyuan
Browse files

gd: add LE advertising callback

Tag: #gd-refactor
Bug: 159815595
Test: gd/cert/run --host
Change-Id: I780bbe31b28374f18feb353250c1ef7c5b253e8d
parent fe29d435
Loading
Loading
Loading
Loading
+187 −38
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct Advertiser {
  AddressWithType current_address;
  common::Callback<void(Address, AddressType)> scan_callback;
  common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback;
  int8_t tx_power;
};

ExtendedAdvertisingConfig::ExtendedAdvertisingConfig(const AdvertisingConfig& config) : AdvertisingConfig(config) {
@@ -113,6 +114,10 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
    return num_instances_;
  }

  void register_advertising_callback(AdvertisingCallback* advertising_callback) {
    advertising_callbacks_ = advertising_callback;
  }

  void register_set_terminated_callback(
      common::ContextualCallback<void(ErrorCode, uint16_t, hci::AddressWithType)> set_terminated_callback) {
    set_terminated_callback_ = std::move(set_terminated_callback);
@@ -178,6 +183,11 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
      address_manager_registered = false;
      paused = false;
    }
    if (advertising_api_type_ == AdvertisingApiType::LE_5_0) {
      le_advertising_interface_->EnqueueCommand(
          hci::LeRemoveAdvertisingSetBuilder::Create(id),
          module_handler_->BindOnce(impl::check_status<LeRemoveAdvertisingSetCompleteView>));
    }
  }

  void create_advertiser(AdvertiserId id, const AdvertisingConfig& config,
@@ -215,14 +225,19 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingDataBuilder::Create(config.advertisement),
            module_handler_->BindOnce(impl::check_status<LeSetAdvertisingDataCompleteView>));
        EnabledSet curr_set;
        curr_set.advertising_handle_ = id;
        enabled_sets_[id] = curr_set;
        if (!paused) {
          std::vector<EnabledSet> enabled_sets = {curr_set};
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
              module_handler_->BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>));
              module_handler_->BindOnceOn(
                  this,
                  &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
                  Enable::ENABLED,
                  enabled_sets));
        }
        EnabledSet curr_set;
        curr_set.advertising_handle_ = id;
        enabled_sets_[id] = curr_set;
      } break;
      case (AdvertisingApiType::ANDROID_HCI): {
        le_advertising_interface_->EnqueueCommand(
@@ -309,10 +324,22 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb

      le_advertising_interface_->EnqueueCommand(
          LeSetExtendedAdvertisingLegacyParametersBuilder::Create(
              id, legacy_properties, config.interval_min, config.interval_max, config.channel_map,
              config.own_address_type, config.peer_address_type, config.peer_address, config.filter_policy,
              config.tx_power, config.sid, config.enable_scan_request_notifications),
          module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingParametersCompleteView>));
              id,
              legacy_properties,
              config.interval_min,
              config.interval_max,
              config.channel_map,
              config.own_address_type,
              config.peer_address_type,
              config.peer_address,
              config.filter_policy,
              config.tx_power,
              config.sid,
              config.enable_scan_request_notifications),
          module_handler_->BindOnceOn(
              this,
              &impl::on_set_extended_advertising_parameters_complete<LeSetExtendedAdvertisingParametersCompleteView>,
              id));
    } else {
      uint8_t legacy_properties = (config.connectable ? 0x1 : 0x00) | (config.scannable ? 0x2 : 0x00) |
                                  (config.directed ? 0x4 : 0x00) | (config.high_duty_directed_connectable ? 0x8 : 0x00);
@@ -321,12 +348,26 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb

      le_advertising_interface_->EnqueueCommand(
          hci::LeSetExtendedAdvertisingParametersBuilder::Create(
              id, legacy_properties, extended_properties, config.interval_min, config.interval_max, config.channel_map,
              config.own_address_type, config.peer_address_type, config.peer_address, config.filter_policy,
              config.tx_power, (config.use_le_coded_phy ? PrimaryPhyType::LE_CODED : PrimaryPhyType::LE_1M),
              config.secondary_max_skip, config.secondary_advertising_phy, config.sid,
              id,
              legacy_properties,
              extended_properties,
              config.interval_min,
              config.interval_max,
              config.channel_map,
              config.own_address_type,
              config.peer_address_type,
              config.peer_address,
              config.filter_policy,
              config.tx_power,
              (config.use_le_coded_phy ? PrimaryPhyType::LE_CODED : PrimaryPhyType::LE_1M),
              config.secondary_max_skip,
              config.secondary_advertising_phy,
              config.sid,
              config.enable_scan_request_notifications),
          module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingParametersCompleteView>));
          module_handler_->BindOnceOn(
              this,
              &impl::on_set_extended_advertising_parameters_complete<LeSetExtendedAdvertisingParametersCompleteView>,
              id));
    }

    if (config.own_address_type == OwnAddressType::RANDOM_DEVICE_ADDRESS) {
@@ -360,7 +401,11 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
    if (!paused) {
      le_advertising_interface_->EnqueueCommand(
          hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::ENABLED, enabled_sets),
          module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
          module_handler_->BindOnceOn(
              this,
              &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
              Enable::ENABLED,
              enabled_sets));
    }
  }

@@ -369,11 +414,19 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
      LOG_INFO("Unknown advertising set %u", advertising_set);
      return;
    }
    EnabledSet curr_set;
    curr_set.advertising_handle_ = advertising_set;
    std::vector<EnabledSet> enabled_vector{curr_set};

    switch (advertising_api_type_) {
      case (AdvertisingApiType::LE_4_0):
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
            module_handler_->BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>));
            module_handler_->BindOnceOn(
                this,
                &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
                Enable::DISABLED,
                enabled_vector));
        break;
      case (AdvertisingApiType::ANDROID_HCI):
        le_advertising_interface_->EnqueueCommand(
@@ -381,12 +434,13 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
            module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
        break;
      case (AdvertisingApiType::LE_5_0): {
        EnabledSet curr_set;
        curr_set.advertising_handle_ = advertising_set;
        std::vector<EnabledSet> enabled_vector{curr_set};
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_vector),
            module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
            module_handler_->BindOnceOn(
                this,
                &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
                Enable::DISABLED,
                enabled_vector));
      } break;
    }

@@ -397,11 +451,23 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
  void OnPause() override {
    paused = true;
    if (!advertising_sets_.empty()) {
      std::vector<EnabledSet> enabled_sets = {};
      for (size_t i = 0; i < enabled_sets_.size(); i++) {
        EnabledSet curr_set = enabled_sets_[i];
        if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
          enabled_sets.push_back(enabled_sets_[i]);
        }
      }

      switch (advertising_api_type_) {
        case (AdvertisingApiType::LE_4_0): {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
              module_handler_->BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>));
              module_handler_->BindOnceOn(
                  this,
                  &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
                  Enable::DISABLED,
                  enabled_sets));
        } break;
        case (AdvertisingApiType::ANDROID_HCI): {
          for (size_t i = 0; i < enabled_sets_.size(); i++) {
@@ -414,17 +480,14 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
          }
        } break;
        case (AdvertisingApiType::LE_5_0): {
          std::vector<EnabledSet> enabled_sets = {};
          for (size_t i = 0; i < enabled_sets_.size(); i++) {
            EnabledSet curr_set = enabled_sets_[i];
            if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
              enabled_sets.push_back(enabled_sets_[i]);
            }
          }
          if (enabled_sets.size() != 0) {
            le_advertising_interface_->EnqueueCommand(
                hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_sets),
                module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
                module_handler_->BindOnceOn(
                    this,
                    &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
                    Enable::DISABLED,
                    enabled_sets));
          }
        } break;
      }
@@ -435,11 +498,23 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
  void OnResume() override {
    paused = false;
    if (!advertising_sets_.empty()) {
      std::vector<EnabledSet> enabled_sets = {};
      for (size_t i = 0; i < enabled_sets_.size(); i++) {
        EnabledSet curr_set = enabled_sets_[i];
        if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
          enabled_sets.push_back(enabled_sets_[i]);
        }
      }

      switch (advertising_api_type_) {
        case (AdvertisingApiType::LE_4_0): {
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
              module_handler_->BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>));
              module_handler_->BindOnceOn(
                  this,
                  &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
                  Enable::ENABLED,
                  enabled_sets));
        } break;
        case (AdvertisingApiType::ANDROID_HCI): {
          for (size_t i = 0; i < enabled_sets_.size(); i++) {
@@ -452,17 +527,14 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
          }
        } break;
        case (AdvertisingApiType::LE_5_0): {
          std::vector<EnabledSet> enabled_sets = {};
          for (size_t i = 0; i < enabled_sets_.size(); i++) {
            EnabledSet curr_set = enabled_sets_[i];
            if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
              enabled_sets.push_back(enabled_sets_[i]);
            }
          }
          if (enabled_sets.size() != 0) {
            le_advertising_interface_->EnqueueCommand(
                hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::ENABLED, enabled_sets),
                module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
                module_handler_->BindOnceOn(
                    this,
                    &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
                    Enable::ENABLED,
                    enabled_sets));
          }
        } break;
      }
@@ -472,6 +544,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb

  common::Callback<void(Address, AddressType)> scan_callback_;
  common::ContextualCallback<void(ErrorCode, uint16_t, hci::AddressWithType)> set_terminated_callback_{};
  AdvertisingCallback* advertising_callbacks_ = nullptr;
  os::Handler* registered_handler_{nullptr};
  Module* module_;
  os::Handler* module_handler_;
@@ -489,13 +562,85 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb

  AdvertisingApiType advertising_api_type_{0};

  template <class View>
  void on_set_advertising_enable_complete(
      Enable enable, std::vector<EnabledSet> enabled_sets, CommandCompleteView view) {
    ASSERT(view.IsValid());
    auto complete_view = LeSetAdvertisingEnableCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
    }

    if (advertising_callbacks_ == nullptr) {
      return;
    }
    for (EnabledSet enabled_set : enabled_sets) {
      uint8_t id = enabled_set.advertising_handle_;
      if (id == kInvalidHandle) {
        continue;
      }
      if (enable == Enable::ENABLED) {
        advertising_callbacks_->onAdvertisingEnabled(id, true, advertising_status);
      } else {
        advertising_callbacks_->onAdvertisingEnabled(id, false, advertising_status);
      }
    }
  }

  template <class View>
  void on_set_extended_advertising_enable_complete(
      Enable enable, std::vector<EnabledSet> enabled_sets, CommandCompleteView view) {
    ASSERT(view.IsValid());
    auto complete_view = LeSetExtendedAdvertisingEnableCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
    AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
      advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
    }

    if (advertising_callbacks_ == nullptr) {
      return;
    }

    for (EnabledSet enabled_set : enabled_sets) {
      int8_t tx_power = advertising_sets_[enabled_set.advertising_handle_].tx_power;
      uint8_t id = enabled_set.advertising_handle_;
      if (id == kInvalidHandle) {
        continue;
      }
      if (enable == Enable::ENABLED) {
        advertising_callbacks_->OnAdvertisingSetStarted(id, tx_power, advertising_status);
      } else {
        advertising_callbacks_->onAdvertisingEnabled(id, false, advertising_status);
      }
    }
  }

  template <class View>
  void on_set_extended_advertising_parameters_complete(AdvertiserId id, CommandCompleteView view) {
    ASSERT(view.IsValid());
    auto complete_view = LeSetExtendedAdvertisingParametersCompleteView::Create(view);
    ASSERT(complete_view.IsValid());
    if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
      LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
      return;
    }
    advertising_sets_[id].tx_power = complete_view.GetSelectedTxPower();
  }

  template <class View>
  static void check_status(CommandCompleteView view) {
    ASSERT(view.IsValid());
    auto status_view = View::Create(view);
    ASSERT(status_view.IsValid());
    if (status_view.GetStatus() != ErrorCode::SUCCESS) {
      LOG_INFO("SetEnable returned status %s", ErrorCodeText(status_view.GetStatus()).c_str());
      LOG_INFO(
          "Got a Command complete %s, status %s",
          OpCodeText(view.GetCommandOpCode()).c_str(),
          ErrorCodeText(status_view.GetStatus()).c_str());
    }
  }
};
@@ -591,6 +736,10 @@ void LeAdvertisingManager::RemoveAdvertiser(AdvertiserId id) {
  GetHandler()->CallOn(pimpl_.get(), &impl::remove_advertiser, id);
}

void LeAdvertisingManager::RegisterAdvertisingCallback(AdvertisingCallback* advertising_callback) {
  CallOn(pimpl_.get(), &impl::register_advertising_callback, advertising_callback);
}

void LeAdvertisingManager::RegisterSetTerminatedCallback(
    common::ContextualCallback<void(ErrorCode, uint16_t, hci::AddressWithType)> set_terminated_callback) {
  GetHandler()->CallOn(pimpl_.get(), &impl::register_set_terminated_callback, set_terminated_callback);
+18 −0
Original line number Diff line number Diff line
@@ -62,6 +62,22 @@ class ExtendedAdvertisingConfig : public AdvertisingConfig {

using AdvertiserId = int32_t;

class AdvertisingCallback {
 public:
  enum AdvertisingStatus {
    SUCCESS,
    DATA_TOO_LARGE,
    TOO_MANY_ADVERTISERS,
    ALREADY_STARTED,
    INTERNAL_ERROR,
    FEATURE_UNSUPPORTED
  };

  virtual ~AdvertisingCallback() = default;
  virtual void OnAdvertisingSetStarted(uint8_t advertiser_id, int8_t tx_power, AdvertisingStatus status) = 0;
  virtual void onAdvertisingEnabled(uint8_t advertiser_id, bool enable, uint8_t status) = 0;
};

class LeAdvertisingManager : public bluetooth::Module {
 public:
  static constexpr AdvertiserId kInvalidId = -1;
@@ -81,6 +97,8 @@ class LeAdvertisingManager : public bluetooth::Module {

  void RemoveAdvertiser(AdvertiserId id);

  void RegisterAdvertisingCallback(AdvertisingCallback* advertising_callback);

  virtual void RegisterSetTerminatedCallback(
      common::ContextualCallback<void(ErrorCode, uint16_t, hci::AddressWithType)> set_terminated_callback);

+27 −0
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ class LeAdvertisingManagerTest : public ::testing::Test {
    ASSERT_NE(client_handler_, nullptr);
    test_controller_->num_advertisers = 1;
    le_advertising_manager_ = fake_registry_.Start<LeAdvertisingManager>(&thread_);
    le_advertising_manager_->RegisterAdvertisingCallback(&mock_advertising_callback_);
  }

  void TearDown() override {
@@ -322,10 +323,24 @@ class LeAdvertisingManagerTest : public ::testing::Test {
    set_terminated_promise_.reset();
  }

  void sync_client_handler() {
    std::promise<void> promise;
    auto future = promise.get_future();
    client_handler_->Call(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
    auto future_status = future.wait_for(std::chrono::seconds(1));
    ASSERT_EQ(future_status, std::future_status::ready);
  }

  std::unique_ptr<std::promise<Address>> address_promise_{};
  std::unique_ptr<std::promise<ErrorCode>> set_terminated_promise_{};

  OpCode param_opcode_{OpCode::LE_SET_ADVERTISING_PARAMETERS};

  class MockAdvertisingCallback : public AdvertisingCallback {
   public:
    MOCK_METHOD3(OnAdvertisingSetStarted, void(uint8_t advertiser_id, int8_t tx_power, AdvertisingStatus status));
    MOCK_METHOD3(onAdvertisingEnabled, void(uint8_t advertiser_id, bool enable, uint8_t status));
  } mock_advertising_callback_;
};

class LeAndroidHciAdvertisingManagerTest : public LeAdvertisingManagerTest {
@@ -377,6 +392,9 @@ TEST_F(LeAdvertisingManagerTest, create_advertiser_test) {
      OpCode::LE_SET_ADVERTISING_DATA,
      OpCode::LE_SET_ADVERTISING_ENABLE,
  };
  EXPECT_CALL(
      mock_advertising_callback_, onAdvertisingEnabled(id, true, AdvertisingCallback::AdvertisingStatus::SUCCESS));

  std::vector<uint8_t> success_vector{static_cast<uint8_t>(ErrorCode::SUCCESS)};
  auto result = last_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
  ASSERT_EQ(std::future_status::ready, result);
@@ -392,7 +410,10 @@ TEST_F(LeAdvertisingManagerTest, create_advertiser_test) {
  le_advertising_manager_->RemoveAdvertiser(id);
  result = last_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
  ASSERT_EQ(std::future_status::ready, result);
  EXPECT_CALL(
      mock_advertising_callback_, onAdvertisingEnabled(id, false, AdvertisingCallback::AdvertisingStatus::SUCCESS));
  test_hci_layer_->IncomingEvent(LeSetAdvertisingEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
  sync_client_handler();
}

TEST_F(LeAndroidHciAdvertisingManagerTest, create_advertiser_test) {
@@ -457,6 +478,8 @@ TEST_F(LeExtendedAdvertisingManagerTest, create_advertiser_test) {
  auto id = le_advertising_manager_->ExtendedCreateAdvertiser(advertising_config, scan_callback,
                                                              set_terminated_callback, client_handler_);
  ASSERT_NE(LeAdvertisingManager::kInvalidId, id);
  EXPECT_CALL(
      mock_advertising_callback_, OnAdvertisingSetStarted(id, -23, AdvertisingCallback::AdvertisingStatus::SUCCESS));
  std::vector<OpCode> adv_opcodes = {
      OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS,
      OpCode::LE_SET_EXTENDED_ADVERTISING_SCAN_RESPONSE,
@@ -478,12 +501,16 @@ TEST_F(LeExtendedAdvertisingManagerTest, create_advertiser_test) {
          CommandCompleteBuilder::Create(uint8_t{1}, adv_opcodes[i], std::make_unique<RawBuilder>(success_vector)));
    }
  }
  sync_client_handler();
  // Disable the advertiser
  last_command_future = test_hci_layer_->GetCommandFuture(OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE);
  le_advertising_manager_->RemoveAdvertiser(id);
  result = last_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
  ASSERT_EQ(std::future_status::ready, result);
  test_hci_layer_->IncomingEvent(LeSetExtendedAdvertisingEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
  EXPECT_CALL(
      mock_advertising_callback_, onAdvertisingEnabled(id, false, AdvertisingCallback::AdvertisingStatus::SUCCESS));
  sync_client_handler();
}
}  // namespace
}  // namespace hci