[Nearby Connections] Use async StartScanning when flag enabled

Creates the feature flag `enable_ble_v2_async_scanning_advertising` which
enables/disables the use of the async StartScanning, StopScanning,
StartAdvertising, StopAdvertising, etc methods over the soon-to-be deprecated
synchronous versions of those methods. Opted for feature flag over NearbyFlag,
as ChromeOS is the only current consumer and doesn't use Mendel.

Also sets the feature flag to enabled in the ServiceControllerRouter, which
is where ChromeOS sets NC feature flags at startup.

This CL also fully links up the asynchronous Scanning methods. Advertising
will be addressed in a follow up CL.

PiperOrigin-RevId: 608158273
This commit is contained in:
Daniel Classon
2024-02-18 12:59:02 -08:00
committed by Copybara-Service
parent 88064b1543
commit f09368247b
7 changed files with 522 additions and 5 deletions
+2
View File
@@ -57,6 +57,7 @@ cc_library(
"//internal/platform:comm",
"//internal/platform:types",
"//internal/platform:uuid",
"//internal/platform/implementation:comm",
"//proto/mediums:web_rtc_signaling_frames_cc_proto",
# TODO: Support WebRTC
"@com_google_absl//absl/container:btree",
@@ -64,6 +65,7 @@ cc_library(
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:bind_front",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/time",
+149 -2
View File
@@ -20,6 +20,7 @@
#include <utility>
#include <vector>
#include "absl/status/status.h"
#include "absl/strings/escaping.h"
#include "absl/time/time.h"
#include "absl/types/optional.h"
@@ -33,8 +34,11 @@
#include "connections/implementation/mediums/utils.h"
#include "connections/power_level.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancelable_alarm.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
@@ -61,8 +65,17 @@ BleV2::BleV2(BluetoothRadio& radio)
BleV2::~BleV2() {
// Destructor is not taking locks, but methods it is calling are.
while (!scanned_service_ids_.empty()) {
StopScanning(*scanned_service_ids_.begin());
if (FeatureFlags::GetInstance()
.GetFlags()
.enable_ble_v2_async_scanning_advertising) {
// If using asynchronous scanning, check the corresponding map.
while (!service_ids_to_scanning_sessions_.empty()) {
StopScanning(service_ids_to_scanning_sessions_.begin()->first);
}
} else {
while (!scanned_service_ids_.empty()) {
StopScanning(*scanned_service_ids_.begin());
}
}
while (!advertising_infos_.empty()) {
StopAdvertising(advertising_infos_.begin()->first);
@@ -249,6 +262,12 @@ bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level,
service_id, std::move(callback),
mediums::bleutils::kCopresenceServiceUuid);
if (FeatureFlags::GetInstance()
.GetFlags()
.enable_ble_v2_async_scanning_advertising) {
return StartAsyncScanningLocked(service_id, power_level);
}
// Check if scan has been activated, if yes, no need to notify client
// to scan again.
if (!scanned_service_ids_.empty()) {
@@ -320,6 +339,11 @@ bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level,
bool BleV2::StopScanning(const std::string& service_id) {
MutexLock lock(&mutex_);
if (FeatureFlags::GetInstance()
.GetFlags()
.enable_ble_v2_async_scanning_advertising) {
return StopAsyncScanningLocked(service_id);
}
if (!IsScanningLocked(service_id)) {
NEARBY_LOGS(INFO) << "Can't turn off BLE scanning because we never "
@@ -329,6 +353,7 @@ bool BleV2::StopScanning(const std::string& service_id) {
discovered_peripheral_tracker_.StopTracking(service_id);
NEARBY_LOGS(INFO) << "Turned off BLE scanning with service id=" << service_id;
scanned_service_ids_.erase(service_id);
// If still has scanner, don't stop the client scanning.
@@ -506,6 +531,13 @@ bool BleV2::IsAdvertisingLocked(const std::string& service_id) const {
}
bool BleV2::IsScanningLocked(const std::string& service_id) const {
if (FeatureFlags::GetInstance()
.GetFlags()
.enable_ble_v2_async_scanning_advertising) {
// If using asynchronous scanning, check the corresponding map.
auto it = service_ids_to_scanning_sessions_.find(service_id);
return it != service_ids_to_scanning_sessions_.end();
}
return scanned_service_ids_.contains(service_id);
}
@@ -888,6 +920,121 @@ bool BleV2::StartGattAdvertisingLocked(
return true;
}
bool BleV2::StartAsyncScanningLocked(absl::string_view service_id,
PowerLevel power_level) {
CHECK(FeatureFlags::GetInstance()
.GetFlags()
.enable_ble_v2_async_scanning_advertising);
// Use the asynchronous StartScanning method instead of the synchronous one.
// Note: using FeatureFlags instead of NearbyFlags as there is no Mendel
// experiment associated with this change, which was driven by ChromeOS.
// Should we check if the map is not empty, and forego scanning if true?
// If so, do we store a nullptr instead of a scanning session ptr?
auto scanning_session = medium_.StartScanning(
mediums::bleutils::kCopresenceServiceUuid,
PowerLevelToTxPowerLevel(power_level),
api::ble_v2::BleMedium::ScanningCallback{
.start_scanning_result =
[this, &service_id](absl::Status status) mutable {
// The `mutex_` is already held here. Use
// `AssumeHeld` to tell the thread
// annotation static analysis that
// `mutex_` is already exclusively
// locked.
// Note: unsure if this is always the case, but when I
// attempted to acquire the lock here I hit a deadlock.
AssumeHeld(mutex_);
if (status.ok()) {
NEARBY_LOGS(INFO) << "BLE V2 async StartScanning started "
"successfully for service ID"
<< &service_id;
} else {
NEARBY_LOGS(ERROR) << "BLE V2 async StartScanning "
"failed for service ID"
<< &service_id << ": " << status;
service_ids_to_scanning_sessions_.erase(service_id);
}
},
.advertisement_found_cb =
[this](api::ble_v2::BlePeripheral& peripheral,
BleAdvertisementData advertisement_data) {
RunOnBleThread([this, &peripheral, advertisement_data]() {
MutexLock lock(&mutex_);
BleV2Peripheral proxy(medium_, peripheral);
discovered_peripheral_tracker_.ProcessFoundBleAdvertisement(
std::move(proxy), advertisement_data,
[this](BleV2Peripheral proxy, int num_slots, int psm,
const std::vector<std::string>&
interesting_service_ids,
mediums::AdvertisementReadResult&
advertisement_read_result) {
// The `mutex_` is already held here. Use
// `AssumeHeld` to tell the thread
// annotation static analysis that
// `mutex_` is already exclusively
// locked.
AssumeHeld(mutex_);
ProcessFetchGattAdvertisementsRequest(
std::move(proxy), num_slots, psm,
interesting_service_ids, advertisement_read_result);
});
});
},
});
service_ids_to_scanning_sessions_.insert(
{std::string(service_id), std::move(scanning_session)});
NEARBY_LOGS(INFO) << "Requested to start BLE scanning with service id="
<< service_id << " size "
<< service_ids_to_scanning_sessions_.size();
if (lost_alarm_ != nullptr && lost_alarm_->IsValid()) {
// We only use one lost alarm, which will check all service IDs for lost
// advertisements.
return true;
}
absl::Duration peripheral_lost_timeout =
absl::Milliseconds(NearbyFlags::GetInstance().GetInt64Flag(
config_package_nearby::nearby_connections_feature::
kBlePeripheralLostTimeoutMillis));
// Set up lost alarm.
lost_alarm_ = std::make_unique<CancelableAlarm>(
"BLE.StartScanning() onLost",
[this]() {
MutexLock lock(&mutex_);
discovered_peripheral_tracker_.ProcessLostGattAdvertisements();
},
peripheral_lost_timeout, &alarm_executor_, /*is_recurring=*/true);
return true;
}
bool BleV2::StopAsyncScanningLocked(absl::string_view service_id) {
CHECK(FeatureFlags::GetInstance()
.GetFlags()
.enable_ble_v2_async_scanning_advertising);
// If using asynchronous scanning, check the corresponding map.
auto scanning_session = service_ids_to_scanning_sessions_.find(service_id);
if (scanning_session == service_ids_to_scanning_sessions_.end()) {
NEARBY_LOGS(INFO) << "Can't turn off async BLE scanning because we never "
"started scanning for this service ID.";
return false;
}
absl::Status status = scanning_session->second->stop_scanning();
if (!status.ok()) {
NEARBY_LOGS(WARNING) << "StopAsyncScanningLocked error: " << status;
}
service_ids_to_scanning_sessions_.erase(scanning_session);
NEARBY_LOGS(INFO) << "Turned off BLE client scanning";
if (lost_alarm_->IsValid()) {
lost_alarm_->Cancel();
}
return true;
}
TxPowerLevel BleV2::PowerLevelToTxPowerLevel(PowerLevel power_level) {
switch (power_level) {
case PowerLevel::kHighPower:
@@ -182,6 +182,13 @@ class BleV2 final {
const ByteArray& medium_advertisement_bytes,
bool extended_advertisement_advertised)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Called by StartScanning when using the async methods.
bool StartAsyncScanningLocked(absl::string_view service_id,
PowerLevel power_level)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Called by StartScanning when using the async methods.
bool StopAsyncScanningLocked(absl::string_view service_id)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
api::ble_v2::TxPowerLevel PowerLevelToTxPowerLevel(PowerLevel power_level);
@@ -204,6 +211,11 @@ class BleV2 final {
absl::flat_hash_set<api::ble_v2::GattCharacteristic>
hosted_gatt_characteristics_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_set<std::string> scanned_service_ids_ ABSL_GUARDED_BY(mutex_);
// This map has the same purpose as the set above, but is used only by
// the async StartScanning method.
absl::flat_hash_map<std::string,
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession>>
service_ids_to_scanning_sessions_ ABSL_GUARDED_BY(mutex_);
std::unique_ptr<CancelableAlarm> lost_alarm_;
mediums::DiscoveredPeripheralTracker discovered_peripheral_tracker_
ABSL_GUARDED_BY(mutex_){medium_.IsExtendedAdvertisementsAvailable()};
@@ -46,6 +46,7 @@ constexpr absl::string_view kServiceIDA =
constexpr absl::string_view kServiceIDB =
"com.google.location.nearby.apps.test.b";
constexpr absl::string_view kAdvertisementString = "\x0a\x0b\x0c\x0d";
constexpr absl::string_view kAdvertisementStringB = "\x01\x02\x03\x04";
class BleV2Test : public testing::TestWithParam<FeatureFlags> {
public:
@@ -577,6 +578,353 @@ TEST_F(BleV2Test, StartScanningDiscoverButNoPeripheralLostAfterStopScanning) {
env_.Stop();
}
TEST_F(BleV2Test, CanStartAsyncScanning) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
BleV2 ble_a(radio_a);
BleV2 ble_b(radio_b);
radio_a.Enable();
radio_b.Enable();
ByteArray advertisement_bytes((std::string(kAdvertisementString)));
CountDownLatch found_latch(1);
ble_b.StartAdvertising(std::string(kServiceIDA), advertisement_bytes,
PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
EXPECT_TRUE(ble_a.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_FALSE(fast_advertisement);
found_latch.CountDown();
},
}));
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
ble_b.StopAdvertising(std::string(kServiceIDA));
EXPECT_TRUE(ble_a.StopScanning(std::string(kServiceIDA)));
env_.Stop();
}
TEST_F(BleV2Test, StartAsyncScanningWithPlatformErrors) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
BleV2 ble_a(radio_a);
BleV2 ble_b(radio_b);
radio_a.Enable();
radio_b.Enable();
ByteArray advertisement_bytes((std::string(kAdvertisementString)));
CountDownLatch found_latch(1);
ble_b.StartAdvertising(std::string(kServiceIDA), advertisement_bytes,
PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
// Disable radio a to simulate platform error.
radio_a.Disable();
EXPECT_FALSE(ble_a.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_FALSE(fast_advertisement);
found_latch.CountDown();
},
}));
radio_a.Enable();
EXPECT_TRUE(ble_a.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_FALSE(fast_advertisement);
found_latch.CountDown();
},
}));
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
ble_b.StopAdvertising(std::string(kServiceIDA));
EXPECT_TRUE(ble_a.StopScanning(std::string(kServiceIDA)));
// Should return false the second time, as we removed service ID from the map.
EXPECT_FALSE(ble_a.StopScanning(std::string(kServiceIDA)));
env_.Stop();
}
TEST_F(BleV2Test, StartAsyncScanningDiscoverAndLostPeripheral) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
BleV2 ble_a(radio_a);
BleV2 ble_b(radio_b);
radio_a.Enable();
radio_b.Enable();
ByteArray advertisement_bytes((std::string(kAdvertisementString)));
CountDownLatch found_latch(1);
CountDownLatch lost_latch(1);
ble_b.StartAdvertising(std::string(kServiceIDA), advertisement_bytes,
PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
EXPECT_TRUE(ble_a.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_FALSE(fast_advertisement);
found_latch.CountDown();
},
.peripheral_lost_cb =
[&lost_latch](
BleV2Peripheral peripheral, const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) { lost_latch.CountDown(); },
}));
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
EXPECT_TRUE(ble_b.StopAdvertising(std::string(kServiceIDA)));
// Wait for a while (2 times delay) to let the alarm occur twice and
// `ProcessLostGattAdvertisements` twice to lost periperal.
SystemClock::Sleep(absl::Milliseconds(kPeripheralLostTimeoutInMillis) * 2);
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
EXPECT_TRUE(ble_a.StopScanning(std::string(kServiceIDA)));
env_.Stop();
}
TEST_F(BleV2Test,
StartAsyncScanningDiscoverButNoPeripheralLostAfterStopScanning) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
BleV2 ble_a(radio_a);
BleV2 ble_b(radio_b);
radio_a.Enable();
radio_b.Enable();
ByteArray advertisement_bytes((std::string(kAdvertisementString)));
CountDownLatch found_latch(1);
CountDownLatch lost_latch(1);
ble_b.StartAdvertising(std::string(kServiceIDA), advertisement_bytes,
PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
EXPECT_TRUE(ble_a.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_FALSE(fast_advertisement);
found_latch.CountDown();
},
.peripheral_lost_cb =
[&lost_latch](
BleV2Peripheral peripheral, const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) { lost_latch.CountDown(); },
}));
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
EXPECT_TRUE(ble_b.StopAdvertising(std::string(kServiceIDA)));
EXPECT_TRUE(ble_a.StopScanning(std::string(kServiceIDA)));
// Don't receive lost peripheral callback because we have stopped scanning and
// cancelled the alarm.
EXPECT_FALSE(lost_latch.Await(kWaitDuration).result());
env_.Stop();
}
TEST_F(BleV2Test, CanStartStopMultipleAsyncScanningWithDifferentServiceIds) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_scanner;
BluetoothRadio radio_advertiser_a;
BluetoothRadio radio_advertiser_b;
BleV2 ble_scanner(radio_scanner);
BleV2 ble_advertiser_a(radio_advertiser_a);
BleV2 ble_advertiser_b(radio_advertiser_b);
radio_scanner.Enable();
radio_advertiser_a.Enable();
radio_advertiser_b.Enable();
ByteArray advertisement_bytes_a((std::string(kAdvertisementString)));
ByteArray advertisement_bytes_b((std::string(kAdvertisementStringB)));
CountDownLatch found_latch_a(1);
CountDownLatch found_latch_b(1);
ble_advertiser_a.StartAdvertising(
std::string(kServiceIDA), advertisement_bytes_a, PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
ble_advertiser_b.StartAdvertising(
std::string(kServiceIDB), advertisement_bytes_b, PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
ble_scanner.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch_a](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(service_id, kServiceIDA);
EXPECT_FALSE(fast_advertisement);
found_latch_a.CountDown();
},
});
ble_scanner.StartScanning(
std::string(kServiceIDB), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch_b](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(service_id, kServiceIDB);
EXPECT_FALSE(fast_advertisement);
found_latch_b.CountDown();
},
});
EXPECT_TRUE(found_latch_a.Await(kWaitDuration).result());
EXPECT_TRUE(found_latch_b.Await(kWaitDuration).result());
EXPECT_TRUE(ble_scanner.StopScanning(std::string(kServiceIDA)));
EXPECT_TRUE(ble_scanner.StopScanning(std::string(kServiceIDB)));
env_.Stop();
}
TEST_F(BleV2Test, StartMultipleAsyncScanningDiscoverAndLostPeripheral) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_scanner;
BluetoothRadio radio_advertiser_a;
BluetoothRadio radio_advertiser_b;
BleV2 ble_scanner(radio_scanner);
BleV2 ble_advertiser_a(radio_advertiser_a);
BleV2 ble_advertiser_b(radio_advertiser_b);
radio_scanner.Enable();
radio_advertiser_a.Enable();
radio_advertiser_b.Enable();
ByteArray advertisement_bytes_a((std::string(kAdvertisementString)));
ByteArray advertisement_bytes_b((std::string(kAdvertisementStringB)));
CountDownLatch found_latch_a(1);
CountDownLatch found_latch_b(1);
CountDownLatch lost_latch_a(1);
CountDownLatch lost_latch_b(1);
ble_advertiser_a.StartAdvertising(
std::string(kServiceIDA), advertisement_bytes_a, PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
ble_advertiser_b.StartAdvertising(
std::string(kServiceIDB), advertisement_bytes_b, PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
ble_scanner.StartScanning(
std::string(kServiceIDA), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch_a](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(service_id, kServiceIDA);
EXPECT_FALSE(fast_advertisement);
found_latch_a.CountDown();
},
.peripheral_lost_cb =
[&lost_latch_a](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(service_id, kServiceIDA);
EXPECT_FALSE(fast_advertisement);
lost_latch_a.CountDown();
},
});
ble_scanner.StartScanning(
std::string(kServiceIDB), PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[&found_latch_b](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(service_id, kServiceIDB);
EXPECT_FALSE(fast_advertisement);
found_latch_b.CountDown();
},
.peripheral_lost_cb =
[&lost_latch_b](BleV2Peripheral peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
EXPECT_EQ(service_id, kServiceIDB);
EXPECT_FALSE(fast_advertisement);
lost_latch_b.CountDown();
},
});
EXPECT_TRUE(found_latch_a.Await(kWaitDuration).result());
EXPECT_TRUE(found_latch_b.Await(kWaitDuration).result());
EXPECT_TRUE(ble_advertiser_a.StopAdvertising(std::string(kServiceIDA)));
// Wait for a while (2 times delay) to let the alarm occur twice and
// `ProcessLostGattAdvertisements` twice to lost periperal.
SystemClock::Sleep(absl::Milliseconds(kPeripheralLostTimeoutInMillis) * 2);
EXPECT_TRUE(lost_latch_a.Await(kWaitDuration).result());
EXPECT_TRUE(ble_advertiser_b.StopAdvertising(std::string(kServiceIDB)));
// Wait for a while (2 times delay) to let the alarm occur twice and
// `ProcessLostGattAdvertisements` twice to lost periperal.
SystemClock::Sleep(absl::Milliseconds(kPeripheralLostTimeoutInMillis) * 2);
EXPECT_TRUE(lost_latch_b.Await(kWaitDuration).result());
EXPECT_TRUE(ble_scanner.StopScanning(std::string(kServiceIDA)));
EXPECT_TRUE(ble_scanner.StopScanning(std::string(kServiceIDB)));
env_.Stop();
}
} // namespace
} // namespace connections
} // namespace nearby
@@ -31,6 +31,7 @@
#include "connections/v3/connections_device.h"
#include "connections/v3/listening_result.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/logging.h"
// TODO(b/285657711): Add tests for uncovered logic, even if trivial.
@@ -97,6 +98,10 @@ ServiceControllerRouter::ServiceControllerRouter(bool enable_ble_v2)
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableBleV2,
enable_ble_v2);
// CrOS uses the async methods for Scanning and Advertising, and has
// no support for the sync version of those methods.
const_cast<FeatureFlags&>(FeatureFlags::GetInstance())
.SetFlags({.enable_ble_v2_async_scanning_advertising = true});
}
}
+3
View File
@@ -62,6 +62,9 @@ class FeatureFlags {
// requested service id before attempting to connect over rfcomm. SDP fails
// on Windows when connecting to FP service id but the rfcomm is successful.
bool skip_service_discovery_before_connecting_to_rfcomm = false;
// Controls enable or disable the use of async methods for StartScanning,
// StopScanning, StartAdvertising, and StopAdvertising for BLE V2.
bool enable_ble_v2_async_scanning_advertising = false;
std::int32_t min_nc_version_supports_safe_to_disconnect = 1;
std::int32_t min_nc_version_supports_auto_reconnect = 3;
+3 -3
View File
@@ -463,9 +463,9 @@ class BleMedium {
};
// Async interface for StartScanning.
// Result status will be passed to start_advertising_result callback.
// To stop advertising, invoke the stop_advertising callback in
// AdvertisingSession.
// Result status will be passed to start_scanning_result callback.
// To stop scanning, invoke the stop_scanning callback in
// ScanningSession.
virtual std::unique_ptr<ScanningSession> StartScanning(
const Uuid& service_uuid, TxPowerLevel tx_power_level,
ScanningCallback callback) = 0;