From 513a41153512af8e41ccec400dffe90a8795c62d Mon Sep 17 00:00:00 2001 From: Chienyuan Date: Thu, 3 Dec 2020 16:41:01 +0800 Subject: [PATCH] gd: implement APIs of Advertising for Android HCI Tag: #gd-refactor Bug: 169125803 Test: cert/run --host Test: atest --host bluetooth_test_gd Change-Id: Iddb9d4838f1fde7f151bd491a3a3ffd3bebf2cdf --- gd/hci/le_advertising_manager.cc | 60 ++++++++++++-- gd/hci/le_advertising_manager_test.cc | 152 +++++++++++++++++++++++++++++++--- 2 files changed, 193 insertions(+), 19 deletions(-) diff --git a/gd/hci/le_advertising_manager.cc b/gd/hci/le_advertising_manager.cc index 9b5665e89..09ef9e51f 100644 --- a/gd/hci/le_advertising_manager.cc +++ b/gd/hci/le_advertising_manager.cc @@ -270,14 +270,16 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb le_advertising_interface_->EnqueueCommand( hci::LeMultiAdvtSetRandomAddrBuilder::Create(advertising_sets_[id].current_address.GetAddress(), id), module_handler_->BindOnce(impl::check_status)); + EnabledSet curr_set; + curr_set.advertising_handle_ = id; + enabled_sets_[id] = curr_set; if (!paused) { + std::vector enabled_sets = {curr_set}; le_advertising_interface_->EnqueueCommand( hci::LeMultiAdvtSetEnableBuilder::Create(Enable::ENABLED, id), - module_handler_->BindOnce(impl::check_status)); + module_handler_->BindOnceOn( + this, &impl::on_set_advertising_enable_complete, 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"); @@ -468,7 +470,19 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb this, &impl::check_status_with_id, 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, advertiser_id)); } break; case (AdvertisingApiType::EXTENDED): { // sid must be in range 0x00 to 0x0F. Since no controller supports more than @@ -561,7 +575,15 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb } } 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, advertiser_id)); + } else { + le_advertising_interface_->EnqueueCommand( + hci::LeMultiAdvtSetDataBuilder::Create(data, advertiser_id), + module_handler_->BindOnceOn(this, &impl::check_status_with_id, advertiser_id)); + } } break; case (AdvertisingApiType::EXTENDED): { uint16_t data_len = 0; @@ -661,7 +683,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb 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, @@ -669,7 +691,10 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb 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, enable, enabled_sets)); } break; case (AdvertisingApiType::EXTENDED): { le_advertising_interface_->EnqueueCommand( @@ -994,6 +1019,25 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb 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()); } diff --git a/gd/hci/le_advertising_manager_test.cc b/gd/hci/le_advertising_manager_test.cc index 5f45a6e5a..7fc77fb3f 100644 --- a/gd/hci/le_advertising_manager_test.cc +++ b/gd/hci/le_advertising_manager_test.cc @@ -131,12 +131,12 @@ class TestHciLayer : public HciLayer { } } - std::future 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>(); - return command_promise_->get_future(); + command_future_ = std::make_unique>(command_promise_->get_future()); } ConnectionManagementCommandView GetCommandPacket(OpCode op_code) { @@ -436,6 +436,54 @@ class LeAndroidHciAdvertisingManagerTest : public LeAdvertisingManagerTest { } }; +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 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 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 { @@ -573,30 +621,32 @@ TEST_F(LeAndroidHciAdvertisingManagerTest, create_advertiser_test) { 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 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) { @@ -657,6 +707,8 @@ 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) { @@ -680,6 +732,27 @@ 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 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; @@ -769,6 +842,39 @@ TEST_F(LeExtendedAdvertisingAPITest, set_data_test) { sync_client_handler(); } +TEST_F(LeAndroidHciAdvertisingAPITest, set_data_test) { + // Set advertising data + std::vector 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 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 advertising_data{}; @@ -921,6 +1027,30 @@ TEST_F(LeAdvertisingAPITest, disable_enable_advertiser_test) { 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(); -- 2.11.0