le_advertising_interface_->EnqueueCommand(
hci::LeMultiAdvtSetRandomAddrBuilder::Create(advertising_sets_[id].current_address.GetAddress(), id),
module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
+ 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::LeMultiAdvtSetEnableBuilder::Create(Enable::ENABLED, id),
- module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
+ module_handler_->BindOnceOn(
+ this, &impl::on_set_advertising_enable_complete<LeMultiAdvtCompleteView>, true, enabled_sets));
}
- EnabledSet curr_set;
- curr_set.advertising_handle_ = id;
- enabled_sets_[id] = curr_set;
} break;
case (AdvertisingApiType::EXTENDED): {
LOG_WARN("Unexpected AdvertisingApiType EXTENDED");
this, &impl::check_status_with_id<LeSetAdvertisingParametersCompleteView>, advertiser_id));
} break;
case (AdvertisingApiType::ANDROID_HCI): {
- // TODO
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeMultiAdvtParamBuilder::Create(
+ config.interval_min,
+ config.interval_max,
+ config.advertising_type,
+ config.own_address_type,
+ config.peer_address_type,
+ config.peer_address,
+ config.channel_map,
+ config.filter_policy,
+ advertiser_id,
+ config.tx_power),
+ module_handler_->BindOnceOn(this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, advertiser_id));
} break;
case (AdvertisingApiType::EXTENDED): {
// sid must be in range 0x00 to 0x0F. Since no controller supports more than
}
} break;
case (AdvertisingApiType::ANDROID_HCI): {
- // TODO
+ if (set_scan_rsp) {
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeMultiAdvtSetScanRespBuilder::Create(data, advertiser_id),
+ module_handler_->BindOnceOn(this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, advertiser_id));
+ } else {
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeMultiAdvtSetDataBuilder::Create(data, advertiser_id),
+ module_handler_->BindOnceOn(this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, advertiser_id));
+ }
} break;
case (AdvertisingApiType::EXTENDED): {
uint16_t data_len = 0;
switch (advertising_api_type_) {
case (AdvertisingApiType::LEGACY): {
le_advertising_interface_->EnqueueCommand(
- hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
+ hci::LeSetAdvertisingEnableBuilder::Create(enable_value),
module_handler_->BindOnceOn(
this,
&impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
enabled_sets));
} break;
case (AdvertisingApiType::ANDROID_HCI): {
- // TODO
+ le_advertising_interface_->EnqueueCommand(
+ hci::LeMultiAdvtSetEnableBuilder::Create(enable_value, advertiser_id),
+ module_handler_->BindOnceOn(
+ this, &impl::on_set_advertising_enable_complete<LeMultiAdvtCompleteView>, enable, enabled_sets));
} break;
case (AdvertisingApiType::EXTENDED): {
le_advertising_interface_->EnqueueCommand(
case OpCode::LE_SET_PERIODIC_ADVERTISING_DATA:
advertising_callbacks_->OnPeriodicAdvertisingDataSet(id, advertising_status);
break;
+ case OpCode::LE_MULTI_ADVT: {
+ auto command_view = LeMultiAdvtCompleteView::Create(view);
+ ASSERT(command_view.IsValid());
+ auto sub_opcode = command_view.GetSubCmd();
+ switch (sub_opcode) {
+ case SubOcf::SET_PARAM:
+ advertising_callbacks_->OnAdvertisingParametersUpdated(
+ id, le_physical_channel_tx_power_, advertising_status);
+ break;
+ case SubOcf::SET_DATA:
+ advertising_callbacks_->OnAdvertisingDataSet(id, advertising_status);
+ break;
+ case SubOcf::SET_SCAN_RESP:
+ advertising_callbacks_->OnScanResponseDataSet(id, advertising_status);
+ break;
+ default:
+ LOG_WARN("Unexpected sub event type %s", SubOcfText(command_view.GetSubCmd()).c_str());
+ }
+ } break;
default:
LOG_WARN("Unexpected event type %s", OpCodeText(view.GetCommandOpCode()).c_str());
}
}
}
- std::future<size_t> GetSubCommandFuture(SubOcf sub_ocf) {
+ void SetSubCommandFuture(SubOcf sub_ocf) {
ASSERT_LOG(command_promise_ == nullptr, "Promises promises ... Only one at a time");
command_op_code_ = OpCode::LE_MULTI_ADVT;
command_sub_ocf_ = sub_ocf;
command_promise_ = std::make_unique<std::promise<size_t>>();
- return command_promise_->get_future();
+ command_future_ = std::make_unique<std::future<size_t>>(command_promise_->get_future());
}
ConnectionManagementCommandView GetCommandPacket(OpCode op_code) {
}
};
+class LeAndroidHciAdvertisingAPITest : public LeAndroidHciAdvertisingManagerTest {
+ protected:
+ void SetUp() override {
+ LeAndroidHciAdvertisingManagerTest::SetUp();
+
+ ExtendedAdvertisingConfig advertising_config{};
+ advertising_config.advertising_type = AdvertisingType::ADV_IND;
+ advertising_config.own_address_type = OwnAddressType::PUBLIC_DEVICE_ADDRESS;
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::FLAGS;
+ data_item.data_ = {0x34};
+ gap_data.push_back(data_item);
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ advertising_config.advertisement = gap_data;
+ advertising_config.scan_response = gap_data;
+
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_PARAM);
+ advertiser_id_ = le_advertising_manager_->ExtendedCreateAdvertiser(
+ 0x00, advertising_config, scan_callback, set_terminated_callback, client_handler_);
+ ASSERT_NE(LeAdvertisingManager::kInvalidId, advertiser_id_);
+ std::vector<SubOcf> sub_ocf = {
+ SubOcf::SET_PARAM,
+ SubOcf::SET_DATA,
+ SubOcf::SET_SCAN_RESP,
+ SubOcf::SET_RANDOM_ADDR,
+ SubOcf::SET_ENABLE,
+ };
+ EXPECT_CALL(
+ mock_advertising_callback_,
+ OnAdvertisingSetStarted(0, advertiser_id_, 0, AdvertisingCallback::AdvertisingStatus::SUCCESS));
+ for (size_t i = 0; i < sub_ocf.size(); i++) {
+ auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ auto sub_packet = LeMultiAdvtView::Create(LeAdvertisingCommandView::Create(packet));
+ ASSERT_TRUE(sub_packet.IsValid());
+ test_hci_layer_->IncomingEvent(LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, sub_ocf[i]));
+ if ((i + 1) < sub_ocf.size()) {
+ test_hci_layer_->SetSubCommandFuture(sub_ocf[i + 1]);
+ }
+ }
+ sync_client_handler();
+ }
+
+ AdvertiserId advertiser_id_;
+};
+
class LeExtendedAdvertisingManagerTest : public LeAdvertisingManagerTest {
protected:
void SetUp() override {
advertising_config.advertisement = gap_data;
advertising_config.scan_response = gap_data;
- auto next_command_future = test_hci_layer_->GetSubCommandFuture(SubOcf::SET_ENABLE);
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_PARAM);
auto id = le_advertising_manager_->ExtendedCreateAdvertiser(
0x00, advertising_config, scan_callback, set_terminated_callback, client_handler_);
ASSERT_NE(LeAdvertisingManager::kInvalidId, id);
std::vector<SubOcf> sub_ocf = {
SubOcf::SET_PARAM, SubOcf::SET_DATA, SubOcf::SET_SCAN_RESP, SubOcf::SET_RANDOM_ADDR, SubOcf::SET_ENABLE,
};
- auto result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
- ASSERT_EQ(std::future_status::ready, result);
- size_t num_commands = next_command_future.get();
+ EXPECT_CALL(
+ mock_advertising_callback_, OnAdvertisingSetStarted(0, id, 0, AdvertisingCallback::AdvertisingStatus::SUCCESS));
for (size_t i = 0; i < sub_ocf.size(); i++) {
auto packet = test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
auto sub_packet = LeMultiAdvtView::Create(LeAdvertisingCommandView::Create(packet));
ASSERT_TRUE(sub_packet.IsValid());
test_hci_layer_->IncomingEvent(LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, sub_ocf[i]));
- num_commands -= 1;
+ if ((i + 1) < sub_ocf.size()) {
+ test_hci_layer_->SetSubCommandFuture(sub_ocf[i + 1]);
+ }
}
- ASSERT_EQ(0, num_commands);
+ sync_client_handler();
+
// Disable the advertiser
- next_command_future = test_hci_layer_->GetSubCommandFuture(SubOcf::SET_ENABLE);
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_ENABLE);
le_advertising_manager_->RemoveAdvertiser(id);
- result = next_command_future.wait_for(std::chrono::duration(std::chrono::milliseconds(100)));
- ASSERT_EQ(std::future_status::ready, result);
+ test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
test_hci_layer_->IncomingEvent(LeMultiAdvtSetEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
+ sync_client_handler();
}
TEST_F(LeExtendedAdvertisingManagerTest, create_advertiser_test) {
TEST_F(LeAdvertisingAPITest, startup_teardown) {}
+TEST_F(LeAndroidHciAdvertisingAPITest, startup_teardown) {}
+
TEST_F(LeExtendedAdvertisingAPITest, startup_teardown) {}
TEST_F(LeAdvertisingAPITest, set_parameter) {
sync_client_handler();
}
+TEST_F(LeAndroidHciAdvertisingAPITest, set_parameter) {
+ ExtendedAdvertisingConfig advertising_config{};
+ advertising_config.advertising_type = AdvertisingType::ADV_IND;
+ advertising_config.own_address_type = OwnAddressType::PUBLIC_DEVICE_ADDRESS;
+ std::vector<GapData> gap_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item.data_ = {'r', 'a', 'n', 'd', 'o', 'm', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ gap_data.push_back(data_item);
+ advertising_config.advertisement = gap_data;
+ advertising_config.channel_map = 1;
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_PARAM);
+ le_advertising_manager_->SetParameters(advertiser_id_, advertising_config);
+ test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ EXPECT_CALL(
+ mock_advertising_callback_,
+ OnAdvertisingParametersUpdated(advertiser_id_, 0x00, AdvertisingCallback::AdvertisingStatus::SUCCESS));
+ test_hci_layer_->IncomingEvent(LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, SubOcf::SET_PARAM));
+ sync_client_handler();
+}
+
TEST_F(LeExtendedAdvertisingAPITest, set_parameter) {
ExtendedAdvertisingConfig advertising_config{};
advertising_config.advertising_type = AdvertisingType::ADV_IND;
sync_client_handler();
}
+TEST_F(LeAndroidHciAdvertisingAPITest, set_data_test) {
+ // Set advertising data
+ std::vector<GapData> advertising_data{};
+ GapData data_item{};
+ data_item.data_type_ = GapDataType::TX_POWER_LEVEL;
+ data_item.data_ = {0x00};
+ advertising_data.push_back(data_item);
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_DATA);
+ le_advertising_manager_->SetData(advertiser_id_, false, advertising_data);
+ test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ EXPECT_CALL(
+ mock_advertising_callback_,
+ OnAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::SUCCESS));
+ test_hci_layer_->IncomingEvent(LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, SubOcf::SET_DATA));
+ sync_client_handler();
+
+ // Set scan response data
+ std::vector<GapData> response_data{};
+ GapData data_item2{};
+ data_item2.data_type_ = GapDataType::COMPLETE_LOCAL_NAME;
+ data_item2.data_ = {'t', 'e', 's', 't', ' ', 'd', 'e', 'v', 'i', 'c', 'e'};
+ response_data.push_back(data_item2);
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_SCAN_RESP);
+ le_advertising_manager_->SetData(advertiser_id_, true, response_data);
+ test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ EXPECT_CALL(
+ mock_advertising_callback_,
+ OnScanResponseDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::SUCCESS));
+ test_hci_layer_->IncomingEvent(
+ LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, SubOcf::SET_SCAN_RESP));
+ sync_client_handler();
+}
+
TEST_F(LeExtendedAdvertisingAPITest, set_data_fragments_test) {
// Set advertising data
std::vector<GapData> advertising_data{};
sync_client_handler();
}
+TEST_F(LeAndroidHciAdvertisingAPITest, disable_enable_advertiser_test) {
+ // disable advertiser
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_ENABLE);
+ le_advertising_manager_->EnableAdvertiser(advertiser_id_, false, 0x00, 0x00);
+ test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ EXPECT_CALL(
+ mock_advertising_callback_,
+ OnAdvertisingEnabled(advertiser_id_, false, AdvertisingCallback::AdvertisingStatus::SUCCESS));
+ test_hci_layer_->IncomingEvent(
+ LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, SubOcf::SET_ENABLE));
+ sync_client_handler();
+
+ // enable advertiser
+ test_hci_layer_->SetSubCommandFuture(SubOcf::SET_ENABLE);
+ le_advertising_manager_->EnableAdvertiser(advertiser_id_, true, 0x00, 0x00);
+ test_hci_layer_->GetCommandPacket(OpCode::LE_MULTI_ADVT);
+ EXPECT_CALL(
+ mock_advertising_callback_,
+ OnAdvertisingEnabled(advertiser_id_, true, AdvertisingCallback::AdvertisingStatus::SUCCESS));
+ test_hci_layer_->IncomingEvent(
+ LeMultiAdvtCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, SubOcf::SET_ENABLE));
+ sync_client_handler();
+}
+
TEST_F(LeExtendedAdvertisingAPITest, disable_enable_advertiser_test) {
// disable advertiser
test_hci_layer_->SetCommandFuture();