Add start/stop legacyDeviceAdvertising in connections ble v2

PiperOrigin-RevId: 621303221
This commit is contained in:
Hai Shang
2024-04-02 14:52:36 -07:00
committed by Copybara-Service
parent 734014a841
commit ca936891c8
3 changed files with 247 additions and 0 deletions
@@ -30,6 +30,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_tracker.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "connections/implementation/mediums/utils.h"
#include "connections/power_level.h"
@@ -230,6 +231,96 @@ bool BleV2::IsAdvertising(const std::string& service_id) const {
return IsAdvertisingLocked(service_id);
}
bool BleV2::StartLegacyAdvertising(
const std::string& input_service_id, const std::string& local_endpoint_id,
const std::string& fast_advertisement_service_uuid) {
NEARBY_LOGS(INFO) << "StartLegacyAdvertising: " << input_service_id.c_str()
<< ", local_endpoint_id: " << local_endpoint_id.c_str();
MutexLock lock(&mutex_);
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO) << "Can't start BLE v2 legacy advertising because "
"Bluetooth was never turned on";
return false;
}
if (!IsAvailableLocked()) {
NEARBY_LOGS(INFO)
<< "Can't turn on BLE v2 legacy advertising. BLE is not available.";
return false;
}
// Checking to avoid conflicts to the bool StartAdvertsing invokes.
// TODO(hais) remove this if check after deprecating bool StartAdvertising.
if (IsAdvertisingLocked(input_service_id)) {
NEARBY_LOGS(INFO) << "Failed to BLE v2 legacy device advertise as ble is "
"already advertising.";
return false;
}
std::string service_id = input_service_id + "-Legacy";
if (service_ids_to_advertising_sessions_.find(service_id) !=
service_ids_to_advertising_sessions_.end()) {
NEARBY_LOGS(INFO) << "Already started legacy device advertising for "
<< service_id;
return false;
}
std::unique_ptr<api::ble_v2::BleMedium::AdvertisingSession>
legacy_device_advertizing_session = medium_.StartAdvertising(
CreateAdvertisingDataForLegacyDevice(),
{.tx_power_level = TxPowerLevel::kMedium, .is_connectable = true},
api::ble_v2::BleMedium::AdvertisingCallback{
.start_advertising_result =
[this, &service_id](absl::Status status) mutable {
AssumeHeld(mutex_);
if (status.ok()) {
NEARBY_LOGS(INFO)
<< "BLE V2 advertising for legacy device started "
"successfully for service ID "
<< &service_id;
} else {
NEARBY_LOGS(ERROR) << "BLE V2 advertising for legacy "
"device failed for service ID "
<< &service_id << ": " << status;
service_ids_to_advertising_sessions_.erase(service_id);
}
},
});
if (legacy_device_advertizing_session == nullptr) {
NEARBY_LOGS(ERROR) << "Failed to turn on BLE v2 advertising for legacy "
"device for service ID "
<< service_id;
return false;
}
service_ids_to_advertising_sessions_.insert(
{std::string(service_id), std::move(legacy_device_advertizing_session)});
return true;
}
bool BleV2::StopLegacyAdvertising(const std::string& input_service_id) {
NEARBY_LOGS(INFO) << "StopLegacyAdvertising:" << input_service_id.c_str();
MutexLock lock(&mutex_);
std::string service_id = input_service_id + "-Legacy";
auto legacy_device_advertising_session =
service_ids_to_advertising_sessions_.find(service_id);
if (legacy_device_advertising_session ==
service_ids_to_advertising_sessions_.end()) {
NEARBY_LOGS(INFO) << "Can't find session to turn off legacy device BLE "
"advertisingfor this service ID: "
<< service_id;
return false;
}
absl::Status status =
legacy_device_advertising_session->second->stop_advertising();
if (!status.ok()) {
NEARBY_LOGS(WARNING) << "StopLegacyAdvertising error: " << status;
}
service_ids_to_advertising_sessions_.erase(legacy_device_advertising_session);
NEARBY_LOGS(INFO) << "Removed advertising-session for " << service_id;
return status.ok();
}
bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level,
DiscoveredPeripheralCallback callback) {
MutexLock lock(&mutex_);
@@ -763,6 +854,19 @@ ByteArray BleV2::CreateAdvertisementHeader(
advertisement_hash, psm));
}
api::ble_v2::BleAdvertisementData
BleV2::CreateAdvertisingDataForLegacyDevice() {
BleAdvertisementData advertising_data;
advertising_data.is_extended_advertisement = false;
ByteArray encoded_bytes{
mediums::DiscoveredPeripheralTracker::kDummyAdvertisementValue};
advertising_data.service_data.insert(
{mediums::bleutils::kCopresenceServiceUuid, encoded_bytes});
return advertising_data;
}
bool BleV2::StartAdvertisingLocked(const std::string& service_id) {
const auto it = advertising_infos_.find(service_id);
if (it == advertising_infos_.end()) {
@@ -78,6 +78,18 @@ class BleV2 final {
bool IsAdvertising(const std::string& service_id) const
ABSL_LOCKS_EXCLUDED(mutex_);
// Use dummy bytes to do ble advertising, only for legacy devices.
// Returns true, if data is successfully set, and false otherwise.
bool StartLegacyAdvertising(
const std::string& service_id, const std::string& local_endpoint_id,
const std::string& fast_advertisement_service_uuid)
ABSL_LOCKS_EXCLUDED(mutex_);
// (TODO:hais) update this after ble_v2 async api refactor.
// Stop Ble advertising with dummy bytes for legagy device.
bool StopLegacyAdvertising(const std::string& service_id)
ABSL_LOCKS_EXCLUDED(mutex_);
// Enables BLE scanning for a service ID. Will report any discoverable
// advertisement data through a callback.
// Returns true, if the scanning is successfully enabled, false otherwise.
@@ -167,6 +179,10 @@ class BleV2 final {
ByteArray CreateAdvertisementHeader(int psm,
bool extended_advertisement_advertised)
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
// For devices that don't have extended nor gatt adverting.
api::ble_v2::BleAdvertisementData CreateAdvertisingDataForLegacyDevice();
bool StartAdvertisingLocked(const std::string& service_id)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool StartFastAdvertisingLocked(
@@ -216,6 +232,11 @@ class BleV2 final {
absl::flat_hash_map<std::string,
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession>>
service_ids_to_scanning_sessions_ ABSL_GUARDED_BY(mutex_);
// Save advertising sessions by service id, used by the async StartAdvertising
// method.
absl::flat_hash_map<
std::string, std::unique_ptr<api::ble_v2::BleMedium::AdvertisingSession>>
service_ids_to_advertising_sessions_ ABSL_GUARDED_BY(mutex_);
std::unique_ptr<CancelableAlarm> lost_alarm_;
mediums::DiscoveredPeripheralTracker discovered_peripheral_tracker_
ABSL_GUARDED_BY(mutex_){medium_.IsExtendedAdvertisementsAvailable()};
@@ -47,6 +47,8 @@ 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";
constexpr absl::string_view kLocalEndpointId = "local_endpoint_id";
constexpr absl::string_view kFastAdvertisementServiceUuid{"\xf3\xfe"};
class BleV2Test : public testing::TestWithParam<FeatureFlags> {
public:
@@ -578,6 +580,126 @@ TEST_F(BleV2Test, StartScanningDiscoverButNoPeripheralLostAfterStopScanning) {
env_.Stop();
}
TEST_F(BleV2Test, CanStartAndStopLegacyAdvertising) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BleV2 ble_a{radio_a};
radio_a.Enable();
std::string service_id(kServiceIDA);
EXPECT_TRUE(
ble_a.StartLegacyAdvertising(service_id, std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid)));
EXPECT_FALSE(ble_a.IsAdvertising(service_id));
EXPECT_TRUE(ble_a.StopLegacyAdvertising(service_id));
env_.Stop();
}
TEST_F(BleV2Test, CanNotStartLegacyAdvertisingWhenRadioNotEnabled) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BleV2 ble_a{radio_a};
radio_a.Disable();
std::string service_id(kServiceIDA);
EXPECT_FALSE(
ble_a.StartLegacyAdvertising(service_id, std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid)));
env_.Stop();
}
TEST_F(BleV2Test, CanNotStopLegacyAdvertisingForNonExistingServiceId) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});
env_.Start();
BluetoothRadio radio_a;
BleV2 ble_a{radio_a};
radio_a.Enable();
std::string service_id(kServiceIDA);
EXPECT_FALSE(ble_a.StopLegacyAdvertising(service_id));
EXPECT_TRUE(
ble_a.StartLegacyAdvertising(service_id, std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble_a.StopLegacyAdvertising(service_id));
env_.Stop();
}
TEST_F(BleV2Test, StartLegacyAdvertisingBlockedByRegularAdvertising) {
env_.Start();
BluetoothRadio radio_a;
BleV2 ble_a{radio_a};
radio_a.Enable();
std::string service_id(kServiceIDA);
ByteArray advertisement_bytes((std::string(kAdvertisementString)));
ble_a.StartAdvertising(std::string(kServiceIDA), advertisement_bytes,
PowerLevel::kHighPower,
/*is_fast_advertisement=*/false);
EXPECT_TRUE(ble_a.IsAdvertising(service_id));
EXPECT_FALSE(
ble_a.StartLegacyAdvertising(service_id, std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid)));
ble_a.StopAdvertising(std::string(kServiceIDA));
env_.Stop();
}
TEST_F(BleV2Test, DuplicateStartLegacyAdvertisingReturnsFalse) {
env_.Start();
BluetoothRadio radio_a;
BleV2 ble_a{radio_a};
radio_a.Enable();
std::string service_id(kServiceIDA);
EXPECT_TRUE(
ble_a.StartLegacyAdvertising(service_id, std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid)));
EXPECT_FALSE(
ble_a.StartLegacyAdvertising(service_id, std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble_a.StopLegacyAdvertising(service_id));
env_.Stop();
}
TEST_F(BleV2Test, HandleLegacyAdvertising) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true,
.enable_invoking_legacy_device_discovered_cb = 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 legacy_device_found_latch(1);
ble_b.StartLegacyAdvertising(std::string(kServiceIDA),
std::string(kLocalEndpointId),
std::string(kFastAdvertisementServiceUuid));
std::string legacy_service_id("NearbySharing");
EXPECT_TRUE(ble_a.StartScanning(
legacy_service_id, PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[](BleV2Peripheral peripheral, const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
FAIL() << "Legacy device shouldn't be reported here.";
},
.legacy_device_discovered_cb =
[&legacy_device_found_latch]() {
legacy_device_found_latch.CountDown();
},
}));
EXPECT_TRUE(legacy_device_found_latch.Await(kWaitDuration).result());
ble_b.StopAdvertising(std::string(kServiceIDA));
EXPECT_TRUE(ble_a.StopScanning(legacy_service_id));
env_.Stop();
}
TEST_F(BleV2Test, CanStartAsyncScanning) {
env_.SetFeatureFlags(
{FeatureFlags{.enable_ble_v2_async_scanning_advertising = true}});