diff --git a/connections/implementation/mediums/ble/discovered_peripheral_tracker.cc b/connections/implementation/mediums/ble/discovered_peripheral_tracker.cc index 6639dd4a..51e2dd53 100644 --- a/connections/implementation/mediums/ble/discovered_peripheral_tracker.cc +++ b/connections/implementation/mediums/ble/discovered_peripheral_tracker.cc @@ -228,6 +228,7 @@ bool DiscoveredPeripheralTracker::HandleOnLostAdvertisementLocked( return false; } + std::vector advertisements_to_clear; for (const auto& hash : on_lost_advertisement->hashes()) { for (const auto& it : gatt_advertisement_infos_) { if (it.second.instant_on_lost_hash.string_data() == hash) { @@ -256,12 +257,16 @@ bool DiscoveredPeripheralTracker::HandleOnLostAdvertisementLocked( << it.second.service_id; } - ClearGattAdvertisement(gatt_advertisement); + advertisements_to_clear.push_back(gatt_advertisement); } break; } } } + + for (const auto& advertisement : advertisements_to_clear) { + ClearGattAdvertisement(advertisement); + } return true; } diff --git a/connections/implementation/mediums/ble/discovered_peripheral_tracker_test.cc b/connections/implementation/mediums/ble/discovered_peripheral_tracker_test.cc index c34120ae..52fb547f 100644 --- a/connections/implementation/mediums/ble/discovered_peripheral_tracker_test.cc +++ b/connections/implementation/mediums/ble/discovered_peripheral_tracker_test.cc @@ -223,6 +223,42 @@ class DiscoveredPeripheralTrackerTest adapter_peripheral_->GetAddress().address()); } + void SetupMultipleAdvertisementsState( + const BleAdvertisementHeader& header, + const BleAdvertisement& advertisement_1, + const BleAdvertisement& advertisement_2) { + MutexLock lock(&discovered_peripheral_tracker_->mutex_); + ByteArray advertisement_bytes_1 = advertisement_1.ByteArrayWithExtraField(); + ByteArray advertisement_bytes_2 = advertisement_2.ByteArrayWithExtraField(); + std::vector gatt_advertisement_bytes_list = { + &advertisement_bytes_1, &advertisement_bytes_2}; + + discovered_peripheral_tracker_->HandleRawGattAdvertisements( + CreateBlePeripheral(), header, gatt_advertisement_bytes_list, + /*service_uuid=*/{}); + } + + void RegisterServiceIdCallback(const std::string& service_id, + CountDownLatch& lost_latch) { + discovered_peripheral_tracker_->StartTracking( + service_id, /*include_dct_advertisement=*/false, Pcp::kP2pPointToPoint, + { + .instant_lost_cb = + [&lost_latch]( + BlePeripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_latch.CountDown(); }, + }, + /*fast_advertisement_service_uuid=*/{}); + } + + bool CallHandleOnLostAdvertisementLocked( + const api::ble::BleAdvertisementData& advertisement_data) { + MutexLock lock(&discovered_peripheral_tracker_->mutex_); + return discovered_peripheral_tracker_->HandleOnLostAdvertisementLocked( + advertisement_data); + } + // Simulates to see a fast advertisement. void FindFastAdvertisement( const api::ble::BleAdvertisementData& advertisement_data, @@ -1267,6 +1303,58 @@ TEST_P(DiscoveredPeripheralTrackerTest, InstantLostPeripheralForInstantOnLost) { EXPECT_TRUE(lost_latch.Await(kWaitDuration).result()); } +TEST_P(DiscoveredPeripheralTrackerTest, + InstantLostPeripheralForInstantOnLost_MultipleAdvertisements) { + ByteArray advertisement_hash = GenerateRandomAdvertisementHash(); + BleAdvertisementHeader header(BleAdvertisementHeader::Version::kV2, + /*extended_advertisement=*/false, + /*num_slots=*/1, ByteArray{}, // bloom filter + advertisement_hash, + BleAdvertisementHeader::kDefaultPsmValue); + + ByteArray advertisement_bytes_1 = CreateBleAdvertisement( + std::string(kServiceIdA), ByteArray(std::string(kData)), + ByteArray(std::string(kDeviceToken))); + ByteArray advertisement_bytes_2 = CreateBleAdvertisement( + std::string(kServiceIdB), ByteArray(std::string(kData2)), + ByteArray(std::string(kDeviceToken))); + + auto adv_status_or_1 = + BleAdvertisement::CreateBleAdvertisement(advertisement_bytes_1); + ASSERT_OK(adv_status_or_1); + BleAdvertisement advertisement_1 = adv_status_or_1.value(); + + auto adv_status_or_2 = + BleAdvertisement::CreateBleAdvertisement(advertisement_bytes_2); + ASSERT_OK(adv_status_or_2); + BleAdvertisement advertisement_2 = adv_status_or_2.value(); + + // Register callbacks for both Service A and Service B. + CountDownLatch lost_latch(2); + RegisterServiceIdCallback(std::string(kServiceIdA), lost_latch); + RegisterServiceIdCallback(std::string(kServiceIdB), lost_latch); + + // Use helper method to set up state manually. + SetupMultipleAdvertisementsState(header, advertisement_1, advertisement_2); + + // Create OnLost advertisement for advertisement_1's hash. + auto advertisement = InstantOnLostAdvertisement::CreateFromHashes( + std::list({std::string(bleutils::GenerateAdvertisementHash( + advertisement_1.ByteArrayWithExtraField()))})); + ASSERT_OK(advertisement); + + api::ble::BleAdvertisementData loss_advertisement_data{}; + loss_advertisement_data.service_data.insert( + {bleutils::kCopresenceServiceUuid, ByteArray(advertisement->ToBytes())}); + + // Call HandleOnLostAdvertisementLocked using helper. + bool result = CallHandleOnLostAdvertisementLocked(loss_advertisement_data); + EXPECT_TRUE(result); + + // Verify that both are lost (callback triggered twice). + EXPECT_TRUE(lost_latch.Await(kWaitDuration).result()); +} + TEST_P(DiscoveredPeripheralTrackerTest, IgnoreFoundAdvertisementForInstantOnLost) { std::vector service_ids = {std::string(kServiceIdA)};