mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
[Nearby Presence] Update ScanManager to trigger changed and lost events
PiperOrigin-RevId: 644072733
This commit is contained in:
committed by
Copybara-Service
parent
5098934e8c
commit
acc38a809b
@@ -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)});
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user