[Nearby Presence] Update ScanManager to trigger changed and lost events

PiperOrigin-RevId: 644072733
This commit is contained in:
Crisrael Lucero
2024-06-17 11:17:00 -07:00
committed by Copybara-Service
parent 5098934e8c
commit acc38a809b
7 changed files with 184 additions and 52 deletions
@@ -1090,6 +1090,10 @@ bool BleV2::StartAsyncScanningLocked(absl::string_view service_id,
});
});
},
.advertisement_lost_cb =
[](api::ble_v2::BlePeripheral& peripheral) {
// TODO(b/345514862): Implement.
},
});
service_ids_to_scanning_sessions_.insert(
{std::string(service_id), std::move(scanning_session)});
+1
View File
@@ -131,6 +131,7 @@ BleV2Medium::StartScanning(const Uuid& service_uuid,
start_scanning_result(status);
},
.advertisement_found_cb = std::move(callback.advertisement_found_cb),
.advertisement_lost_cb = std::move(callback.advertisement_lost_cb),
});
}
@@ -460,6 +460,8 @@ class BleMedium {
absl::AnyInvocable<void(BlePeripheral& peripheral,
BleAdvertisementData advertisement_data)>
advertisement_found_cb = [](BlePeripheral&, BleAdvertisementData) {};
absl::AnyInvocable<void(BlePeripheral& peripheral)>
advertisement_lost_cb = [](BlePeripheral&) {};
};
// Async interface for StartScanning.
+49 -36
View File
@@ -315,11 +315,15 @@ void MediumEnvironment::OnBleV2PeripheralStateChanged(
NEARBY_LOGS(INFO) << "G3 [Run] OnBleServiceStateChanged [peripheral impl="
<< &peripheral << "]; context=" << &context
<< "; notify=" << enabled;
if (enabled) {
for (auto& element : context.scan_callback_map) {
if (element.first.first == service_id)
for (auto& element : context.scan_callback_map) {
if (element.first.first == service_id) {
if (enabled) {
element.second.advertisement_found_cb(peripheral,
ble_advertisement_data);
} else {
element.second.advertisement_lost_cb(peripheral);
}
}
}
}
@@ -610,39 +614,48 @@ void MediumEnvironment::UpdateBleV2MediumForAdvertising(
auto& context = it->second;
context.ble_peripheral = &peripheral;
context.advertising = enabled;
if (enabled) {
context.advertisement_data = advertisement_data;
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForAdvertising: this=" << this
<< ", medium=" << &medium << ", medium_context=" << &context
<< ", peripheral=" << &peripheral << ", enabled=" << enabled;
for (auto& medium_info : ble_v2_mediums_) {
const api::ble_v2::BleMedium* remote_medium = medium_info.first;
BleV2MediumContext& remote_context = medium_info.second;
// Do not send notification to the same medium.
if (remote_medium == &medium) continue;
// Do not send notification to the medium that is not scanning.
if (!remote_context.scanning) continue;
absl::flat_hash_set<Uuid> remote_scanning_service_uuids;
for (auto& element : remote_context.scan_callback_map) {
remote_scanning_service_uuids.insert(element.first.first);
}
for (auto& remote_scanning_service_uuid :
remote_scanning_service_uuids) {
auto const it = context.advertisement_data.service_data.find(
remote_scanning_service_uuid);
if (it == context.advertisement_data.service_data.end()) continue;
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForAdvertising, found other medium="
<< remote_medium
<< ", remote_medium_context=" << &remote_context
<< ", remote_context.peripheral="
<< remote_context.ble_peripheral
<< ". Ready to call OnBleV2PeripheralStateChanged.";
OnBleV2PeripheralStateChanged(
enabled, remote_context, remote_scanning_service_uuid,
context.advertisement_data, *context.ble_peripheral);
}
context.advertisement_data = advertisement_data;
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForAdvertising: this=" << this
<< ", medium=" << &medium << ", medium_context=" << &context
<< ", peripheral=" << &peripheral << ", enabled=" << enabled;
for (auto& medium_info : ble_v2_mediums_) {
const api::ble_v2::BleMedium* remote_medium = medium_info.first;
BleV2MediumContext& remote_context = medium_info.second;
// Do not send notification to the same medium.
if (remote_medium == &medium) continue;
// Do not send notification to the medium that is not scanning.
if (!remote_context.scanning) continue;
absl::flat_hash_set<Uuid> remote_scanning_service_uuids;
for (auto& element : remote_context.scan_callback_map) {
remote_scanning_service_uuids.insert(element.first.first);
}
for (auto& remote_scanning_service_uuid :
remote_scanning_service_uuids) {
auto const it = context.advertisement_data.service_data.find(
remote_scanning_service_uuid);
// Only skip when service data is not found and the medium is
// enabled. Mediums that stop advertising (disabled) pass in empty
// advertisement data but should still be processed.
if (it == context.advertisement_data.service_data.end()
&& enabled) continue;
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForAdvertising, found other medium="
<< remote_medium
<< ", remote_medium_context=" << &remote_context
<< ", remote_context.peripheral="
<< remote_context.ble_peripheral
<< ". Ready to call OnBleV2PeripheralStateChanged.";
OnBleV2PeripheralStateChanged(
enabled, remote_context, remote_scanning_service_uuid,
context.advertisement_data, *context.ble_peripheral);
}
}
});
+70 -14
View File
@@ -74,6 +74,15 @@ ScanSessionId ScanManager::StartScan(ScanRequest scan_request,
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) {
NotifyFoundBle(id, data, address);
});
},
.advertisement_lost_cb =
[this, id](BlePeripheral& peripheral) {
RunOnServiceControllerThread(
"notify-lost-ble",
[this, id, address = peripheral.GetAddress()]()
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_) {
NotifyLostBle(id, address);
});
}};
FetchCredentials(id, scan_request);
scan_sessions_.insert(
@@ -107,12 +116,14 @@ void ScanManager::StopScan(ScanSessionId id) {
void ScanManager::NotifyFoundBle(ScanSessionId id, BleAdvertisementData data,
absl::string_view remote_address) {
auto advertisement_data =
data.service_data[kPresenceServiceUuid].AsStringView();
auto it = scan_sessions_.find(id);
if (it == scan_sessions_.end()) {
return;
}
auto advertisement_data =
data.service_data[kPresenceServiceUuid].AsStringView();
auto advert = it->second.decoder.DecodeAdvertisement(advertisement_data);
if (!advert.ok()) {
// This advertisement is not relevant to the current element, skip.
@@ -123,20 +134,65 @@ void ScanManager::NotifyFoundBle(ScanSessionId id, BleAdvertisementData data,
internal::DeviceIdentityMetaData device_identity_metadata;
device_identity_metadata.set_bluetooth_mac_address(
std::string(remote_address));
PresenceDevice device(DeviceMotion(), device_identity_metadata,
advert->identity_type);
// Ok if the advertisement is for trusted/private identity.
if (advert->public_credential.ok()) {
device.SetDecryptSharedCredential(*(advert->public_credential));
}
device.AddExtendedProperties(advert->data_elements);
for (const auto& data_element : advert->data_elements) {
if (data_element.GetType() == DataElement::kActionFieldType) {
device.AddAction(PresenceAction(static_cast<int>(
static_cast<uint8_t>(data_element.GetValue()[0]))));
if (!device_address_to_endpoint_id_map_.contains(remote_address)) {
PresenceDevice device(DeviceMotion(), device_identity_metadata,
advert->identity_type);
// Ok if the advertisement is for trusted/private identity.
if (advert->public_credential.ok()) {
device.SetDecryptSharedCredential(*(advert->public_credential));
}
device.AddExtendedProperties(advert->data_elements);
for (const auto& data_element : advert->data_elements) {
if (data_element.GetType() == DataElement::kActionFieldType) {
device.AddAction(PresenceAction(static_cast<int>(
static_cast<uint8_t>(data_element.GetValue()[0]))));
}
}
device_address_to_endpoint_id_map_.emplace(remote_address,
device.GetEndpointId());
it->second.callback.on_discovered_cb(std::move(device));
} else {
PresenceDevice device(
device_address_to_endpoint_id_map_.at(remote_address));
device.SetDeviceIdentityMetaData(device_identity_metadata);
// Ok if the advertisement is for trusted/private identity.
if (advert->public_credential.ok()) {
device.SetDecryptSharedCredential(*(advert->public_credential));
}
device.AddExtendedProperties(advert->data_elements);
for (const auto& data_element : advert->data_elements) {
if (data_element.GetType() == DataElement::kActionFieldType) {
device.AddAction(PresenceAction(static_cast<int>(
static_cast<uint8_t>(data_element.GetValue()[0]))));
}
}
it->second.callback.on_updated_cb(std::move(device));
}
it->second.callback.on_discovered_cb(std::move(device));
}
}
void ScanManager::NotifyLostBle(ScanSessionId id,
absl::string_view remote_address) {
auto it = scan_sessions_.find(id);
if (it == scan_sessions_.end()) {
return;
}
if (device_address_to_endpoint_id_map_.contains(remote_address)) {
internal::DeviceIdentityMetaData device_identity_metadata;
device_identity_metadata.set_bluetooth_mac_address(
std::string(remote_address));
PresenceDevice device(
device_address_to_endpoint_id_map_.at(remote_address));
device.SetDeviceIdentityMetaData(device_identity_metadata);
device_address_to_endpoint_id_map_.erase(remote_address);
it->second.callback.on_lost_cb(std::move(device));
}
}
+5
View File
@@ -84,6 +84,8 @@ class ScanManager {
void NotifyFoundBle(ScanSessionId id, BleAdvertisementData data,
absl::string_view remote_address)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_);
void NotifyLostBle(ScanSessionId id, absl::string_view remote_address)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_);
void FetchCredentials(ScanSessionId id, const ScanRequest& scan_request)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_);
void UpdateCredentials(ScanSessionId id, IdentityType identity_type,
@@ -96,6 +98,9 @@ class ScanManager {
CredentialManager* credential_manager_;
absl::flat_hash_map<ScanSessionId, ScanSessionState> scan_sessions_
ABSL_GUARDED_BY(*executor_);
absl::flat_hash_map<std::string, std::string>
device_address_to_endpoint_id_map_
ABSL_GUARDED_BY(*executor_);
SingleThreadExecutor* executor_;
};
+53 -2
View File
@@ -56,7 +56,6 @@ using AdvertisingCallback =
using ::nearby::SingleThreadExecutor;
using CountDownLatch = ::nearby::CountDownLatch;
// using ::testing::UnorderedElementsAre;
using ::testing::Contains;
class ScanManagerTest : public testing::Test {
@@ -104,7 +103,11 @@ class ScanManagerTest : public testing::Test {
}
},
.on_discovered_cb =
[this](PresenceDevice pd) { found_latch_.CountDown(); }};
[this](PresenceDevice pd) { found_latch_.CountDown(); },
.on_updated_cb =
[this](PresenceDevice pd) { updated_latch_.CountDown(); },
.on_lost_cb =
[this](PresenceDevice pd) { lost_latch_.CountDown(); }};
}
std::vector<nearby::internal::IdentityType> MakeDefaultIdentityTypes() {
@@ -120,6 +123,8 @@ class ScanManagerTest : public testing::Test {
nearby::MediumEnvironment& env_ = {nearby::MediumEnvironment::Instance()};
CountDownLatch start_latch_{1};
CountDownLatch found_latch_{1};
CountDownLatch updated_latch_{1};
CountDownLatch lost_latch_{1};
};
TEST_F(ScanManagerTest, CanStartThenStopScanning) {
@@ -213,6 +218,21 @@ TEST_F(ScanManagerTest, PresenceMetadataIsRetained) {
found_latch_.CountDown();
}
},
.on_updated_cb =
[this, &address](PresenceDevice pd) {
if (pd.GetDeviceIdentityMetadata().bluetooth_mac_address() ==
address) {
EXPECT_THAT(pd.GetExtendedProperties(),
Contains(DataElement(ActionBit::kNearbyShareAction))
.Times(1));
EXPECT_THAT(
pd.GetActions(),
Contains(PresenceAction{(int)ActionBit::kNearbyShareAction})
.Times(1));
updated_latch_.CountDown();
}
}};
// Start scanning
ScanRequest scan_request_no_filter = MakeDefaultScanRequest();
@@ -224,6 +244,37 @@ TEST_F(ScanManagerTest, PresenceMetadataIsRetained) {
ASSERT_TRUE(mediums.GetBle().IsAvailable());
EXPECT_TRUE(start_latch_.Await().Ok());
EXPECT_TRUE(found_latch_.Await().Ok());
// Advertise again to trigger `on_updated_cb`
advertising_session = StartAdvertisingOn(ble2);
EXPECT_TRUE(updated_latch_.Await().Ok());
manager.StopScan(scan_session);
EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 0);
}
TEST_F(ScanManagerTest, DiscoverThenLoseAdvertisement) {
Mediums mediums;
ScanManager manager(mediums, credential_manager_, executor_);
// Set up advertiser
nearby::BluetoothAdapter server_adapter;
Ble ble2(server_adapter);
std::unique_ptr<AdvertisingSession> advertising_session =
StartAdvertisingOn(ble2);
// Start scanning
ScanSessionId scan_session =
manager.StartScan(MakeDefaultScanRequest(), MakeDefaultScanCallback());
EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 1);
EXPECT_TRUE(start_latch_.Await().Ok());
EXPECT_TRUE(found_latch_.Await().Ok());
// Stop advertising to trigger `on_lost_cb`
EXPECT_OK(advertising_session->stop_advertising());
env_.Sync();
EXPECT_TRUE(lost_latch_.Await().Ok());
manager.StopScan(scan_session);
EXPECT_EQ(manager.ScanningCallbacksLengthForTest(), 0);
}