[Nearby Connections]: Avoid modifying gatt_advertisement_infos_ while iterating.

PiperOrigin-RevId: 926231653
This commit is contained in:
hai007
2026-06-03 13:29:24 -07:00
committed by Copybara-Service
parent 00c8ae557a
commit 0e578f71d4
2 changed files with 94 additions and 1 deletions
@@ -228,6 +228,7 @@ bool DiscoveredPeripheralTracker::HandleOnLostAdvertisementLocked(
return false;
}
std::vector<BleAdvertisement> 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;
}
@@ -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<const ByteArray*> 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>({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<std::string> service_ids = {std::string(kServiceIdA)};