Optimized instant on lost

PiperOrigin-RevId: 659567920
This commit is contained in:
Guogang Li
2024-08-05 08:49:36 -07:00
committed by Copybara-Service
parent 12371764e6
commit c4812a2082
10 changed files with 443 additions and 14 deletions
+21 -1
View File
@@ -1193,7 +1193,7 @@ BasePcpHandler::GetDiscoveredEndpoints(const std::string& endpoint_id) {
std::vector<BasePcpHandler::DiscoveredEndpoint*>
BasePcpHandler::GetDiscoveredEndpoints(
const location::nearby::proto::connections::Medium medium) {
location::nearby::proto::connections::Medium medium) {
std::vector<BasePcpHandler::DiscoveredEndpoint*> result;
MutexLock lock(&discovered_endpoint_mutex_);
for (const auto& item : discovered_endpoints_) {
@@ -1674,6 +1674,26 @@ void BasePcpHandler::OnEndpointLost(
}
}
void BasePcpHandler::OnInstantLost(ClientProxy* client,
const std::string& endpoint_id,
const ByteArray& endpoint_info) {
NEARBY_LOGS(INFO) << "OnInstantLost: id=" << endpoint_id;
std::vector<BasePcpHandler::DiscoveredEndpoint*> discovered_endpoints =
GetDiscoveredEndpoints(endpoint_id);
if (discovered_endpoints.empty()) {
return;
}
for (auto& discovered_endpoint : discovered_endpoints) {
if (discovered_endpoint->endpoint_info == endpoint_info) {
OnEndpointLost(client, *discovered_endpoint);
}
}
NEARBY_LOGS(INFO) << "Reported lost endpoint " << endpoint_id
<< " on all mediums.";
}
Status BasePcpHandler::UpdateAdvertisingOptions(
ClientProxy* client, absl::string_view service_id,
const AdvertisingOptions& advertising_options) {
@@ -292,6 +292,10 @@ class BasePcpHandler : public PcpHandler,
RUN_ON_PCP_HANDLER_THREAD()
ABSL_LOCKS_EXCLUDED(discovered_endpoint_mutex_);
void OnInstantLost(ClientProxy* client, const std::string& endpoint_id,
const ByteArray& endpoint_info)
RUN_ON_PCP_HANDLER_THREAD();
Exception OnIncomingConnection(
ClientProxy* client, const ByteArray& remote_endpoint_info,
std::unique_ptr<EndpointChannel> endpoint_channel,
@@ -379,7 +383,7 @@ class BasePcpHandler : public PcpHandler,
// Returns a vector of discovered endpoints that share a given Medium.
std::vector<BasePcpHandler::DiscoveredEndpoint*> GetDiscoveredEndpoints(
const location::nearby::proto::connections::Medium medium)
location::nearby::proto::connections::Medium medium)
ABSL_LOCKS_EXCLUDED(discovered_endpoint_mutex_);
// Start alarms for endpoints lost by their mediums. Used when updating
@@ -398,7 +402,7 @@ class BasePcpHandler : public PcpHandler,
absl::string_view service_id, StartOperationResult result);
mediums::WebrtcPeerId CreatePeerIdFromAdvertisement(
const string& service_id, const string& endpoint_id,
const std::string& service_id, const std::string& endpoint_id,
const ByteArray& endpoint_info);
SingleThreadExecutor* GetPcpHandlerThread()
@@ -36,6 +36,8 @@
#include "connections/implementation/bwu_manager.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/encryption_runner.h"
#include "connections/implementation/endpoint_channel.h"
#include "connections/implementation/endpoint_channel_manager.h"
#include "connections/implementation/endpoint_manager.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/mediums/mediums.h"
@@ -58,11 +60,14 @@
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/future.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/pipe.h"
#include "proto/connections_enums.pb.h"
#include "proto/connections_enums.proto.h"
namespace nearby {
namespace connections {
@@ -262,6 +267,12 @@ class MockPcpHandler : public BasePcpHandler {
ABSL_NO_THREAD_SAFETY_ANALYSIS {
BasePcpHandler::OnEndpointLost(client, endpoint);
}
void OnInstantLost(ClientProxy* client,
std::shared_ptr<DiscoveredEndpoint> endpoint)
ABSL_NO_THREAD_SAFETY_ANALYSIS {
BasePcpHandler::OnInstantLost(client, endpoint->endpoint_id,
endpoint->endpoint_info);
}
BasePcpHandler::DiscoveredEndpoint* GetDiscoveredEndpoint(
const std::string& endpoint_id) {
return BasePcpHandler::GetDiscoveredEndpoint(endpoint_id);
@@ -417,6 +428,13 @@ class BasePcpHandlerTest
endpoint_distance_changed_cb;
};
void SetUp() override {
// Disable instant on lost for all tests by default.
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableInstantOnLost,
false);
}
void StartAdvertising(ClientProxy* client, MockPcpHandler* pcp_handler,
BooleanMediumSelector allowed = GetParam()) {
AdvertisingOptions advertising_options{
@@ -850,6 +868,14 @@ class BasePcpHandlerTest
.AsStdFunction(),
};
}
void EnableInstantOnLostFeature() {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
connections::config_package_nearby::nearby_connections_feature::
kEnableInstantOnLost,
true);
}
SetSafeToDisconnect set_safe_to_disconnect_{true};
MediumEnvironment& env_ = MediumEnvironment::Instance();
NiceMock<MockNearbyDevice> mock_device_;
@@ -986,6 +1012,77 @@ TEST_P(BasePcpHandlerTest, StartStopStartDiscoveryClearsEndpoints) {
env_.Stop();
}
TEST_F(BasePcpHandlerTest, ShouldLostEndpointWhenReportInstantLost) {
EnableInstantOnLostFeature();
env_.Start({.use_simulated_clock = true});
BooleanMediumSelector allowed{
.bluetooth = true,
.ble = true,
.wifi_lan = true,
};
auto endpoint = std::make_shared<MockDiscoveredEndpoint>(
MockDiscoveredEndpoint{{"ABCD", ByteArray("1234"), "service", Medium::BLE,
WebRtcState::kUndefined},
MockContext{nullptr}});
ClientProxy client;
Mediums m;
EndpointChannelManager ecm;
EndpointManager em(&ecm);
BwuManager bwu(m, em, ecm, {}, {});
MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu);
StartDiscovery(&client, &pcp_handler, allowed);
EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call);
pcp_handler.OnEndpointFound(&client, endpoint);
EXPECT_EQ(pcp_handler.GetDiscoveredEndpoints("ABCD").size(), 1);
EXPECT_CALL(mock_discovery_listener_.endpoint_lost_cb, Call);
pcp_handler.OnInstantLost(&client, endpoint);
EXPECT_EQ(pcp_handler.GetDiscoveredEndpoints("ABCD").size(), 0);
EXPECT_CALL(pcp_handler, StopDiscoveryImpl(&client)).Times(1);
pcp_handler.StopDiscovery(&client);
bwu.Shutdown();
env_.Stop();
}
TEST_F(BasePcpHandlerTest, ShouldLostAllEndpointsWhenReportInstantLost) {
EnableInstantOnLostFeature();
env_.Start({.use_simulated_clock = true});
BooleanMediumSelector allowed{
.bluetooth = true,
.ble = true,
.wifi_lan = true,
};
auto endpoint = std::make_shared<MockDiscoveredEndpoint>(
MockDiscoveredEndpoint{{"ABCD", ByteArray("1234"), "service", Medium::BLE,
WebRtcState::kUndefined},
MockContext{nullptr}});
auto endpoint_bluetooth = std::make_shared<MockDiscoveredEndpoint>(
MockDiscoveredEndpoint{{"ABCD", ByteArray("1234"), "service",
Medium::BLUETOOTH, WebRtcState::kUndefined},
MockContext{nullptr}});
ClientProxy client;
Mediums m;
EndpointChannelManager ecm;
EndpointManager em(&ecm);
BwuManager bwu(m, em, ecm, {}, {});
MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu);
StartDiscovery(&client, &pcp_handler, allowed);
EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call);
pcp_handler.OnEndpointFound(&client, endpoint);
pcp_handler.OnEndpointFound(&client, endpoint_bluetooth);
EXPECT_EQ(pcp_handler.GetDiscoveredEndpoints("ABCD").size(), 2);
EXPECT_CALL(mock_discovery_listener_.endpoint_lost_cb, Call);
pcp_handler.OnInstantLost(&client, endpoint);
EXPECT_EQ(pcp_handler.GetDiscoveredEndpoints("ABCD").size(), 0);
EXPECT_CALL(pcp_handler, StopDiscoveryImpl(&client)).Times(1);
pcp_handler.StopDiscovery(&client);
bwu.Shutdown();
env_.Stop();
}
TEST_F(BasePcpHandlerTest, WifiMediumFailFallBackToBT) {
env_.Start();
std::string service_id{"service"};
@@ -2431,8 +2528,8 @@ TEST_F(BasePcpHandlerTest, IncomingConnectionFailsWithEmptyEndpointId) {
.local_endpoint_id = "",
.local_endpoint_info = ByteArray("local endpoint"),
});
// At this point the connection request doesn't have an endpoint ID field set,
// so we do that here.
// At this point the connection request doesn't have an endpoint ID field
// set, so we do that here.
location::nearby::connections::OfflineFrame frame;
frame.ParseFromString(serialized_frame.AsStringView());
frame.mutable_v1()->mutable_connection_request()->set_endpoint_id("");
@@ -53,6 +53,7 @@ cc_library(
"//internal/platform:util",
"//internal/platform:uuid",
"//internal/platform/implementation:comm",
"//internal/platform/implementation:types",
"//proto/mediums:ble_frames_cc_proto",
"@aappleby_smhasher//:libmurmur3",
"@com_google_absl//absl/base:core_headers",
@@ -37,7 +37,12 @@ struct DiscoveredPeripheralCallback {
const ByteArray& advertisement_bytes, bool fast_advertisement)>
peripheral_lost_cb =
[](BleV2Peripheral, const std::string&, const ByteArray&, bool) {};
absl::AnyInvocable<void(void)> legacy_device_discovered_cb = [](){};
absl::AnyInvocable<void(
BleV2Peripheral peripheral, const std::string& service_id,
const ByteArray& advertisement_bytes, bool fast_advertisement)>
instant_lost_cb =
[](BleV2Peripheral, const std::string&, const ByteArray&, bool) {};
absl::AnyInvocable<void(void)> legacy_device_discovered_cb = []() {};
};
} // namespace mediums
@@ -24,6 +24,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/time/time.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/mediums/ble_v2/advertisement_read_result.h"
#include "connections/implementation/mediums/ble_v2/ble_advertisement.h"
@@ -38,6 +39,7 @@
#include "internal/platform/byte_array.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/system_clock.h"
#include "internal/platform/logging.h"
#include "internal/platform/multi_thread_executor.h"
#include "internal/platform/mutex_lock.h"
@@ -50,7 +52,8 @@ namespace connections {
namespace mediums {
namespace {
constexpr int kGattThreadCount = 1;
}
constexpr absl::Duration kInstantLostAdvertisementTimeout = absl::Seconds(60);
} // namespace
DiscoveredPeripheralTracker::DiscoveredPeripheralTracker(
bool is_extended_advertisement_available)
@@ -188,10 +191,20 @@ bool DiscoveredPeripheralTracker::HandleOnLostAdvertisementLocked(
BleV2Peripheral lost_peripheral = it.second.peripheral;
lost_peripheral.SetId(ByteArray(gatt_advertisement));
if (gatt_advertisement.IsValid()) {
discovery_cb_it->second.discovered_peripheral_callback
.peripheral_lost_cb(lost_peripheral, it.second.service_id,
gatt_advertisement.GetData(),
gatt_advertisement.IsFastAdvertisement());
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::
kEnableInstantOnLost)) {
AddInstantLostAdvertisement(it.second.advertisement_header);
discovery_cb_it->second.discovered_peripheral_callback
.instant_lost_cb(lost_peripheral, it.second.service_id,
gatt_advertisement.GetData(),
gatt_advertisement.IsFastAdvertisement());
} else {
discovery_cb_it->second.discovered_peripheral_callback
.peripheral_lost_cb(lost_peripheral, it.second.service_id,
gatt_advertisement.GetData(),
gatt_advertisement.IsFastAdvertisement());
}
NEARBY_LOGS(INFO)
<< __func__ << ": OnLost triggered for service_id "
<< it.second.service_id;
@@ -423,6 +436,16 @@ BleAdvertisementHeader DiscoveredPeripheralTracker::HandleRawGattAdvertisements(
peripheral.SetPsm(new_psm);
BleV2Peripheral discovered_peripheral = peripheral;
discovered_peripheral.SetId(ByteArray(gatt_advertisement));
if (IsInstantLostAdvertisement(new_advertisement_header)) {
NEARBY_LOGS(INFO)
<< "Skip the advertisement with hash "
<< absl::BytesToHexString(
new_advertisement_header.GetAdvertisementHash()
.AsStringView())
<< " due to it was reported lost.";
continue;
}
sii_it->second.discovered_peripheral_callback.peripheral_discovered_cb(
std::move(discovered_peripheral), service_id,
gatt_advertisement.GetData(),
@@ -557,7 +580,7 @@ bool DiscoveredPeripheralTracker::IsDummyAdvertisementHeader(
// Do not count advertisementHash and psm value here, for L2CAP feature, the
// regular advertisement has different value, it will include PSM value if
// received it from extended advertisement protocol and it will not has PSM
// value if it fetcted from GATT connection.
// value if it fetched from GATT connection.
BloomFilter bloom_filter(
std::make_unique<BitSetImpl<
BleAdvertisementHeader::kServiceIdBloomFilterByteLength>>());
@@ -855,6 +878,48 @@ bool DiscoveredPeripheralTracker::IsLegacyDeviceAdvertisementData(
ByteArray(DiscoveredPeripheralTracker::kDummyAdvertisementValue);
}
bool DiscoveredPeripheralTracker::IsInstantLostAdvertisement(
const BleAdvertisementHeader& advertisement_header) {
RemoveExpiredInstantLostAdvertisements();
return lost_advertisment_infos_.contains(
std::string(advertisement_header.GetAdvertisementHash()));
}
void DiscoveredPeripheralTracker::AddInstantLostAdvertisement(
const BleAdvertisementHeader& advertisement_header) {
NEARBY_LOGS(INFO)
<< "Add instant lost advertisement "
<< absl::BytesToHexString(
advertisement_header.GetAdvertisementHash().AsStringView());
lost_advertisment_infos_[std::string(
advertisement_header.GetAdvertisementHash())] =
SystemClock::ElapsedRealtime();
}
void DiscoveredPeripheralTracker::RemoveExpiredInstantLostAdvertisements() {
absl::Time now = SystemClock::ElapsedRealtime();
if (now - last_lost_info_update_time_ < kInstantLostAdvertisementTimeout) {
return;
}
auto it = lost_advertisment_infos_.begin(),
end = lost_advertisment_infos_.end();
NEARBY_LOGS(INFO) << "Start to remove expired lost advertisements.";
int count = 0;
while (it != end) {
if (now - it->second >= kInstantLostAdvertisementTimeout) {
lost_advertisment_infos_.erase(it++);
++count;
} else {
++it;
}
}
last_lost_info_update_time_ = now;
NEARBY_LOGS(INFO) << "Removed " << count << " expired lost advertisements.";
}
} // namespace mediums
} // namespace connections
} // namespace nearby
@@ -15,6 +15,7 @@
#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_TRACKER_H_
#define CORE_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_TRACKER_H_
#include <array>
#include <memory>
#include <string>
#include <vector>
@@ -23,6 +24,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/functional/any_invocable.h"
#include "absl/time/time.h"
#include "connections/implementation/mediums//lost_entity_tracker.h"
#include "connections/implementation/mediums/ble_v2/advertisement_read_result.h"
#include "connections/implementation/mediums/ble_v2/ble_advertisement.h"
@@ -31,8 +33,10 @@
#include "connections/implementation/mediums/lost_entity_tracker.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/multi_thread_executor.h"
#include "internal/platform/mutex.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace connections {
@@ -230,7 +234,7 @@ class DiscoveredPeripheralTracker {
// AdvertisementData.
//
// advertisement_fetcher : a fetcher passed from BLE medium to read the
// advertisemeent from BLE characteristics by GATT server.
// advertisement from BLE characteristics by GATT server.
std::vector<const ByteArray*> FetchRawAdvertisements(
BleV2Peripheral peripheral,
const BleAdvertisementHeader& advertisement_header,
@@ -262,6 +266,16 @@ class DiscoveredPeripheralTracker {
static bool IsLegacyDeviceAdvertisementData(
const api::ble_v2::BleAdvertisementData& advertisement_data);
// Helps to handle advertisement for Instant On lost.
bool IsInstantLostAdvertisement(
const BleAdvertisementHeader& advertisement_header)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void AddInstantLostAdvertisement(
const BleAdvertisementHeader& advertisement_header)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void RemoveExpiredInstantLostAdvertisements()
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Mutex mutex_;
bool is_extended_advertisement_available_;
@@ -310,6 +324,13 @@ class DiscoveredPeripheralTracker {
std::unique_ptr<MultiThreadExecutor> executor_ ABSL_GUARDED_BY(mutex_) =
nullptr;
// Maps an advertisement header's hash with the time it's reported lost.
// Ignores subsequent discovery events for the same advertisement header.
absl::flat_hash_map<std::string, absl::Time> lost_advertisment_infos_
ABSL_GUARDED_BY(mutex_);
absl::Time last_lost_info_update_time_ ABSL_GUARDED_BY(mutex_) =
absl::InfinitePast();
};
} // namespace mediums
@@ -31,6 +31,7 @@
#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h"
#include "connections/implementation/mediums/ble_v2/ble_utils.h"
#include "connections/implementation/mediums/ble_v2/bloom_filter.h"
#include "connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h"
#include "connections/implementation/mediums/ble_v2/instant_on_lost_advertisement.h"
#include "connections/implementation/mediums/utils.h"
#include "internal/flags/nearby_flags.h"
@@ -133,6 +134,20 @@ ByteArray GenerateRandomAdvertisementHash() {
return random_advertisement_hash;
}
class MockDiscoveredPeripheralCallback : public DiscoveredPeripheralCallback {
public:
MOCK_METHOD(void, OnPeripheralDiscovered,
(BleV2Peripheral, const std::string&, const ByteArray&, bool),
());
MOCK_METHOD(void, OnPeripheralLost,
(BleV2Peripheral, const std::string&, const ByteArray&, bool),
());
MOCK_METHOD(void, OnInstantLost,
(BleV2Peripheral, const std::string&, const ByteArray&, bool),
());
MOCK_METHOD(void, OnLegacyDeviceDiscovered, (), ());
};
class DiscoveredPeripheralTrackerTest : public testing::Test {
public:
void SetUp() override {
@@ -140,6 +155,9 @@ class DiscoveredPeripheralTrackerTest : public testing::Test {
config_package_nearby::nearby_connections_feature::
kDisableBluetoothClassicScanning,
false);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableInstantOnLost,
false);
MediumEnvironment::Instance().Start();
adapter_peripheral_ = std::make_unique<BluetoothAdapter>();
adapter_central_ = std::make_unique<BluetoothAdapter>();
@@ -190,6 +208,12 @@ class DiscoveredPeripheralTrackerTest : public testing::Test {
true);
}
void EnableInstantOnLost() {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableInstantOnLost,
true);
}
protected:
// A stub Advertisement fetcher.
DiscoveredPeripheralTracker::AdvertisementFetcher GetAdvertisementFetcher(
@@ -1104,6 +1128,145 @@ TEST_F(DiscoveredPeripheralTrackerTest, LostPeripheralForInstantOnLost) {
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
}
TEST_F(DiscoveredPeripheralTrackerTest, InstantLostPeripheralForInstantOnLost) {
EnableInstantOnLost();
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
ByteArray advertisement_header_bytes =
CreateBleAdvertisementHeader(advertisement_hash, service_ids);
ByteArray advertisement_bytes = CreateBleAdvertisement(
std::string(kServiceIdA), ByteArray(std::string(kData)),
ByteArray(std::string(kDeviceToken)));
CountDownLatch found_latch(1);
CountDownLatch lost_latch(1);
CountDownLatch fetch_latch(1);
discovered_peripheral_tracker_.StartTracking(
std::string(kServiceIdA),
{
.peripheral_discovered_cb =
[&found_latch](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(advertisement_bytes, ByteArray(std::string(kData)));
EXPECT_FALSE(fast_advertisement);
found_latch.CountDown();
},
.instant_lost_cb =
[&lost_latch](
BleV2Peripheral peripheral, const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) { lost_latch.CountDown(); },
},
{});
api::ble_v2::BleAdvertisementData advertisement_data{};
if (!advertisement_header_bytes.Empty()) {
advertisement_data.service_data.insert(
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
}
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
// We should receive a client callback of a peripheral discovery.
fetch_latch.Await(kWaitDuration);
ASSERT_TRUE(found_latch.Await(kWaitDuration).result());
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 1);
auto advertisement = InstantOnLostAdvertisement::CreateFromHashes(
std::list<std::string>({std::string(advertisement_hash)}));
ASSERT_OK(advertisement);
api::ble_v2::BleAdvertisementData loss_advertisement_data{};
loss_advertisement_data.service_data.insert(
{bleutils::kCopresenceServiceUuid, ByteArray(advertisement->ToBytes())});
FindAdvertisement(loss_advertisement_data,
{ByteArray(advertisement->ToBytes())}, fetch_latch);
// Then, go through a cycle of onLost. Since we triggered a forced loss via
// the instant on los advertisement, the lost call should trigger the onLost
// client callback.
discovered_peripheral_tracker_.ProcessLostGattAdvertisements();
// We should receive a client callback of a lost peripheral
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
}
TEST_F(DiscoveredPeripheralTrackerTest,
IgnoreFoundAdvertisementForInstantOnLost) {
EnableInstantOnLost();
std::vector<std::string> service_ids = {std::string(kServiceIdA)};
ByteArray advertisement_hash = GenerateRandomAdvertisementHash();
ByteArray advertisement_header_bytes =
CreateBleAdvertisementHeader(advertisement_hash, service_ids);
ByteArray advertisement_bytes = CreateBleAdvertisement(
std::string(kServiceIdA), ByteArray(std::string(kData)),
ByteArray(std::string(kDeviceToken)));
CountDownLatch fetch_latch(1);
MockDiscoveredPeripheralCallback mock_callback;
discovered_peripheral_tracker_.StartTracking(
std::string(kServiceIdA),
{
.peripheral_discovered_cb =
[&mock_callback](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
mock_callback.OnPeripheralDiscovered(peripheral, service_id,
advertisement_bytes,
fast_advertisement);
},
.instant_lost_cb =
[&mock_callback](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
mock_callback.OnInstantLost(peripheral, service_id,
advertisement_bytes,
fast_advertisement);
},
},
{});
api::ble_v2::BleAdvertisementData advertisement_data{};
if (!advertisement_header_bytes.Empty()) {
advertisement_data.service_data.insert(
{bleutils::kCopresenceServiceUuid, advertisement_header_bytes});
}
EXPECT_CALL(mock_callback, OnPeripheralDiscovered).Times(1);
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
fetch_latch.Await(kWaitDuration);
// We should receive a client callback of a peripheral discovery.
EXPECT_EQ(GetFetchAdvertisementCallbackCount(), 1);
auto advertisement = InstantOnLostAdvertisement::CreateFromHashes(
std::list<std::string>({std::string(advertisement_hash)}));
ASSERT_OK(advertisement);
api::ble_v2::BleAdvertisementData loss_advertisement_data{};
loss_advertisement_data.service_data.insert(
{bleutils::kCopresenceServiceUuid, ByteArray(advertisement->ToBytes())});
EXPECT_CALL(mock_callback, OnInstantLost).Times(1);
FindAdvertisement(loss_advertisement_data,
{ByteArray(advertisement->ToBytes())}, fetch_latch);
fetch_latch.Await(kWaitDuration);
// Then, go through a cycle of onLost. Since we triggered a forced loss via
// the instant on los advertisement, the lost call should trigger the onLost
// client callback.
discovered_peripheral_tracker_.ProcessLostGattAdvertisements();
// Lost advertisement should not be reported.
EXPECT_CALL(mock_callback, OnPeripheralDiscovered).Times(0);
FindAdvertisement(advertisement_data, {advertisement_bytes}, fetch_latch);
fetch_latch.Await(kWaitDuration);
}
TEST_F(DiscoveredPeripheralTrackerTest,
LostPeripheralWithFastAdvertisementForInstantOnLost) {
ByteArray fast_advertisement_bytes = CreateFastBleAdvertisement(
@@ -872,6 +872,54 @@ void P2pClusterPcpHandler::BleV2PeripheralLostHandler(
});
}
void P2pClusterPcpHandler::BleV2InstantLostHandler(
ClientProxy* client, BleV2Peripheral peripheral,
const std::string& service_id, const ByteArray& advertisement_bytes,
bool fast_advertisement) {
RunOnPcpHandlerThread(
"p2p-ble-peripheral-instant-lost",
[this, client, service_id, peripheral = std::move(peripheral),
advertisement_bytes, fast_advertisement]() RUN_ON_PCP_HANDLER_THREAD() {
std::string service_id = client->GetDiscoveryServiceId();
if (!client->IsDiscovering() || stop_.Get()) {
NEARBY_LOGS(WARNING)
<< "Ignoring instant lost BlePeripheral "
<< absl::BytesToHexString(peripheral.GetId().data())
<< " because we are no longer discovering.";
return;
}
NEARBY_LOGS(INFO) << "Processing instant lost on BlePeripheral "
<< absl::BytesToHexString(peripheral.GetId().data());
auto ble_status_or = BleAdvertisement::CreateBleAdvertisement(
fast_advertisement, advertisement_bytes);
if (!ble_status_or.ok()) {
NEARBY_LOGS(ERROR) << ble_status_or.status();
return;
}
const auto& advertisement = ble_status_or.value();
// Make sure the BLE advertisement points to a valid
// endpoint we're discovering.
if (!IsRecognizedBleV2Endpoint(service_id, advertisement)) return;
// Remove this BlePeripheral from found_ble_endpoints_, and
// report the endpoint as lost to the client.
auto const item =
found_endpoints_in_ble_discover_cb_.find(peripheral.GetId());
if (item == found_endpoints_in_ble_discover_cb_.end()) {
return;
}
found_endpoints_in_ble_discover_cb_.erase(item);
// Report the instant lost endpoint.
OnInstantLost(client, advertisement.GetEndpointId(),
advertisement.GetEndpointInfo());
});
}
void P2pClusterPcpHandler::BleV2LegacyDeviceDiscoveredHandler() {
if (!NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::
@@ -1783,7 +1831,6 @@ void P2pClusterPcpHandler::StartBluetoothDiscoveryWithPause(
location::nearby::proto::connections::BLE) !=
mediums_started_successfully.end()) {
if (bluetooth_medium_.IsDiscovering(service_id)) {
NEARBY_LOGS(INFO) << "xxxxx";
// If we are already discovering, we don't need to start again.
Medium bluetooth_medium = StartBluetoothDiscovery(client, service_id);
if (bluetooth_medium !=
@@ -2245,6 +2292,8 @@ Medium P2pClusterPcpHandler::StartBleV2Scanning(
.peripheral_lost_cb = absl::bind_front(
&P2pClusterPcpHandler::BleV2PeripheralLostHandler, this,
client),
.instant_lost_cb = absl::bind_front(
&P2pClusterPcpHandler::BleV2InstantLostHandler, this, client),
.legacy_device_discovered_cb = absl::bind_front(
&P2pClusterPcpHandler::BleV2LegacyDeviceDiscoveredHandler,
this),
@@ -248,6 +248,10 @@ class P2pClusterPcpHandler : public BasePcpHandler {
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement);
void BleV2InstantLostHandler(ClientProxy* client, BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement);
void BleV2LegacyDeviceDiscoveredHandler();
void BleV2ConnectionAcceptedHandler(ClientProxy* client,