mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Optimized instant on lost
PiperOrigin-RevId: 659567920
This commit is contained in:
committed by
Copybara-Service
parent
12371764e6
commit
c4812a2082
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user