Loading system/gd/hci/le_advertising_manager.cc +64 −12 Original line number Diff line number Diff line Loading @@ -591,6 +591,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb for (int i = 0; i < data.size(); i++) { if (data[i].size() > kLeMaximumFragmentLength) { LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength); if (advertising_callbacks_ != nullptr) { if (set_scan_rsp) { advertising_callbacks_->OnScanResponseDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR); Loading @@ -598,6 +599,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_callbacks_->OnAdvertisingDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR); } } return; } data_len += data[i].size(); Loading Loading @@ -730,13 +732,63 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb } void set_periodic_data(AdvertiserId advertiser_id, std::vector<GapData> data) { // TODO(b/149221472): Support fragmentation auto operation = Operation::COMPLETE_ADVERTISEMENT; uint16_t data_len = 0; // check data size for (int i = 0; i < data.size(); i++) { if (data[i].size() > kLeMaximumFragmentLength) { LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength); if (advertising_callbacks_ != nullptr) { advertising_callbacks_->OnPeriodicAdvertisingDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR); } return; } data_len += data[i].size(); } if (data_len > le_maximum_advertising_data_length_) { LOG_WARN( "advertising data len exceeds le_maximum_advertising_data_length_ %d", le_maximum_advertising_data_length_); if (advertising_callbacks_ != nullptr) { advertising_callbacks_->OnPeriodicAdvertisingDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE); } return; } if (data_len <= kLeMaximumFragmentLength) { send_periodic_data_fragment(advertiser_id, data, Operation::COMPLETE_ADVERTISEMENT); } else { std::vector<GapData> sub_data; uint16_t sub_data_len = 0; Operation operation = Operation::FIRST_FRAGMENT; for (int i = 0; i < data.size(); i++) { if (sub_data_len + data[i].size() > kLeMaximumFragmentLength) { send_periodic_data_fragment(advertiser_id, sub_data, operation); operation = Operation::INTERMEDIATE_FRAGMENT; sub_data_len = 0; sub_data.clear(); } sub_data.push_back(data[i]); sub_data_len += data[i].size(); } send_periodic_data_fragment(advertiser_id, sub_data, Operation::LAST_FRAGMENT); } } void send_periodic_data_fragment(AdvertiserId advertiser_id, std::vector<GapData> data, Operation operation) { if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) { le_advertising_interface_->EnqueueCommand( hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data), module_handler_->BindOnceOn( this, &impl::check_status_with_id<LeSetPeriodicAdvertisingDataCompleteView>, advertiser_id)); } else { // For first and intermediate fragment, do not trigger advertising_callbacks_. le_advertising_interface_->EnqueueCommand( hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data), module_handler_->BindOnce(impl::check_status<LeSetPeriodicAdvertisingDataCompleteView>)); } } void enable_periodic_advertising(AdvertiserId advertiser_id, bool enable) { Loading system/gd/hci/le_advertising_manager_test.cc +80 −0 Original line number Diff line number Diff line Loading @@ -1104,6 +1104,86 @@ TEST_F(LeExtendedAdvertisingAPITest, set_periodic_data_test) { sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, set_periodic_data_fragments_test) { // Set advertising data std::vector<GapData> advertising_data{}; for (uint8_t i = 0; i < 3; i++) { GapData data_item{}; data_item.data_.push_back(0xfa); data_item.data_type_ = GapDataType::SERVICE_DATA_128_BIT_UUIDS; uint8_t uuid[16] = {0xf0, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, i}; std::copy_n(uuid, 16, std::back_inserter(data_item.data_)); uint8_t service_data[232]; std::copy_n(service_data, 232, std::back_inserter(data_item.data_)); advertising_data.push_back(data_item); } le_advertising_manager_->SetPeriodicData(advertiser_id_, advertising_data); // First fragment test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommandPacket(OpCode::LE_SET_PERIODIC_ADVERTISING_DATA); // Intermediate fragment test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommandPacket(OpCode::LE_SET_PERIODIC_ADVERTISING_DATA); // Last fragment test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommandPacket(OpCode::LE_SET_PERIODIC_ADVERTISING_DATA); EXPECT_CALL( mock_advertising_callback_, OnPeriodicAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::SUCCESS)); test_hci_layer_->IncomingEvent(LeSetPeriodicAdvertisingDataCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS)); test_hci_layer_->IncomingEvent(LeSetPeriodicAdvertisingDataCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS)); test_hci_layer_->IncomingEvent(LeSetPeriodicAdvertisingDataCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS)); sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, set_perodic_data_with_invalid_ad_structure) { // Set advertising data with AD structure that length greater than 251 std::vector<GapData> advertising_data{}; GapData data_item{}; data_item.data_.push_back(0xfb); data_item.data_type_ = GapDataType::SERVICE_DATA_128_BIT_UUIDS; uint8_t uuid[16] = {0xf0, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}; std::copy_n(uuid, 16, std::back_inserter(data_item.data_)); uint8_t service_data[233]; std::copy_n(service_data, 233, std::back_inserter(data_item.data_)); advertising_data.push_back(data_item); EXPECT_CALL( mock_advertising_callback_, OnPeriodicAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR)); le_advertising_manager_->SetPeriodicData(advertiser_id_, advertising_data); sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, set_perodic_data_with_invalid_length) { // Set advertising data with data that greater than le_maximum_advertising_data_length_ std::vector<GapData> advertising_data{}; for (uint8_t i = 0; i < 10; i++) { GapData data_item{}; data_item.data_.push_back(0xfb); data_item.data_type_ = GapDataType::SERVICE_DATA_128_BIT_UUIDS; uint8_t uuid[16] = {0xf0, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, i}; std::copy_n(uuid, 16, std::back_inserter(data_item.data_)); uint8_t service_data[200]; std::copy_n(service_data, 200, std::back_inserter(data_item.data_)); advertising_data.push_back(data_item); } EXPECT_CALL( mock_advertising_callback_, OnPeriodicAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE)); le_advertising_manager_->SetPeriodicData(advertiser_id_, advertising_data); sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, disable_enable_periodic_advertiser_test) { // disable advertiser test_hci_layer_->SetCommandFuture(); Loading Loading
system/gd/hci/le_advertising_manager.cc +64 −12 Original line number Diff line number Diff line Loading @@ -591,6 +591,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb for (int i = 0; i < data.size(); i++) { if (data[i].size() > kLeMaximumFragmentLength) { LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength); if (advertising_callbacks_ != nullptr) { if (set_scan_rsp) { advertising_callbacks_->OnScanResponseDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR); Loading @@ -598,6 +599,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb advertising_callbacks_->OnAdvertisingDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR); } } return; } data_len += data[i].size(); Loading Loading @@ -730,13 +732,63 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb } void set_periodic_data(AdvertiserId advertiser_id, std::vector<GapData> data) { // TODO(b/149221472): Support fragmentation auto operation = Operation::COMPLETE_ADVERTISEMENT; uint16_t data_len = 0; // check data size for (int i = 0; i < data.size(); i++) { if (data[i].size() > kLeMaximumFragmentLength) { LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength); if (advertising_callbacks_ != nullptr) { advertising_callbacks_->OnPeriodicAdvertisingDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR); } return; } data_len += data[i].size(); } if (data_len > le_maximum_advertising_data_length_) { LOG_WARN( "advertising data len exceeds le_maximum_advertising_data_length_ %d", le_maximum_advertising_data_length_); if (advertising_callbacks_ != nullptr) { advertising_callbacks_->OnPeriodicAdvertisingDataSet( advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE); } return; } if (data_len <= kLeMaximumFragmentLength) { send_periodic_data_fragment(advertiser_id, data, Operation::COMPLETE_ADVERTISEMENT); } else { std::vector<GapData> sub_data; uint16_t sub_data_len = 0; Operation operation = Operation::FIRST_FRAGMENT; for (int i = 0; i < data.size(); i++) { if (sub_data_len + data[i].size() > kLeMaximumFragmentLength) { send_periodic_data_fragment(advertiser_id, sub_data, operation); operation = Operation::INTERMEDIATE_FRAGMENT; sub_data_len = 0; sub_data.clear(); } sub_data.push_back(data[i]); sub_data_len += data[i].size(); } send_periodic_data_fragment(advertiser_id, sub_data, Operation::LAST_FRAGMENT); } } void send_periodic_data_fragment(AdvertiserId advertiser_id, std::vector<GapData> data, Operation operation) { if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) { le_advertising_interface_->EnqueueCommand( hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data), module_handler_->BindOnceOn( this, &impl::check_status_with_id<LeSetPeriodicAdvertisingDataCompleteView>, advertiser_id)); } else { // For first and intermediate fragment, do not trigger advertising_callbacks_. le_advertising_interface_->EnqueueCommand( hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data), module_handler_->BindOnce(impl::check_status<LeSetPeriodicAdvertisingDataCompleteView>)); } } void enable_periodic_advertising(AdvertiserId advertiser_id, bool enable) { Loading
system/gd/hci/le_advertising_manager_test.cc +80 −0 Original line number Diff line number Diff line Loading @@ -1104,6 +1104,86 @@ TEST_F(LeExtendedAdvertisingAPITest, set_periodic_data_test) { sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, set_periodic_data_fragments_test) { // Set advertising data std::vector<GapData> advertising_data{}; for (uint8_t i = 0; i < 3; i++) { GapData data_item{}; data_item.data_.push_back(0xfa); data_item.data_type_ = GapDataType::SERVICE_DATA_128_BIT_UUIDS; uint8_t uuid[16] = {0xf0, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, i}; std::copy_n(uuid, 16, std::back_inserter(data_item.data_)); uint8_t service_data[232]; std::copy_n(service_data, 232, std::back_inserter(data_item.data_)); advertising_data.push_back(data_item); } le_advertising_manager_->SetPeriodicData(advertiser_id_, advertising_data); // First fragment test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommandPacket(OpCode::LE_SET_PERIODIC_ADVERTISING_DATA); // Intermediate fragment test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommandPacket(OpCode::LE_SET_PERIODIC_ADVERTISING_DATA); // Last fragment test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommandPacket(OpCode::LE_SET_PERIODIC_ADVERTISING_DATA); EXPECT_CALL( mock_advertising_callback_, OnPeriodicAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::SUCCESS)); test_hci_layer_->IncomingEvent(LeSetPeriodicAdvertisingDataCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS)); test_hci_layer_->IncomingEvent(LeSetPeriodicAdvertisingDataCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS)); test_hci_layer_->IncomingEvent(LeSetPeriodicAdvertisingDataCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS)); sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, set_perodic_data_with_invalid_ad_structure) { // Set advertising data with AD structure that length greater than 251 std::vector<GapData> advertising_data{}; GapData data_item{}; data_item.data_.push_back(0xfb); data_item.data_type_ = GapDataType::SERVICE_DATA_128_BIT_UUIDS; uint8_t uuid[16] = {0xf0, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}; std::copy_n(uuid, 16, std::back_inserter(data_item.data_)); uint8_t service_data[233]; std::copy_n(service_data, 233, std::back_inserter(data_item.data_)); advertising_data.push_back(data_item); EXPECT_CALL( mock_advertising_callback_, OnPeriodicAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR)); le_advertising_manager_->SetPeriodicData(advertiser_id_, advertising_data); sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, set_perodic_data_with_invalid_length) { // Set advertising data with data that greater than le_maximum_advertising_data_length_ std::vector<GapData> advertising_data{}; for (uint8_t i = 0; i < 10; i++) { GapData data_item{}; data_item.data_.push_back(0xfb); data_item.data_type_ = GapDataType::SERVICE_DATA_128_BIT_UUIDS; uint8_t uuid[16] = {0xf0, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, i}; std::copy_n(uuid, 16, std::back_inserter(data_item.data_)); uint8_t service_data[200]; std::copy_n(service_data, 200, std::back_inserter(data_item.data_)); advertising_data.push_back(data_item); } EXPECT_CALL( mock_advertising_callback_, OnPeriodicAdvertisingDataSet(advertiser_id_, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE)); le_advertising_manager_->SetPeriodicData(advertiser_id_, advertising_data); sync_client_handler(); } TEST_F(LeExtendedAdvertisingAPITest, disable_enable_periodic_advertiser_test) { // disable advertiser test_hci_layer_->SetCommandFuture(); Loading