From 412f9e0752d4142644ce21830fe9f6e69c72dba7 Mon Sep 17 00:00:00 2001 From: edwinwu Date: Tue, 17 May 2022 05:39:36 -0700 Subject: [PATCH] [BLE Refactor] Connects BleV2 mediums to PCP handler. PiperOrigin-RevId: 449196646 --- connections/discovery_options.h | 14 +- connections/implementation/base_pcp_handler.h | 9 + .../ble_v2/discovered_peripheral_callback.h | 12 +- .../ble_v2/discovered_peripheral_tracker.cc | 4 +- .../discovered_peripheral_tracker_test.cc | 44 +- .../implementation/mediums/ble_v2_test.cc | 32 +- connections/implementation/mediums/mediums.cc | 2 + connections/implementation/mediums/mediums.h | 5 + .../implementation/p2p_cluster_pcp_handler.cc | 521 ++++++++++++++++-- .../implementation/p2p_cluster_pcp_handler.h | 41 +- internal/platform/ble_v2.h | 1 + internal/platform/feature_flags.h | 2 + 12 files changed, 590 insertions(+), 97 deletions(-) diff --git a/connections/discovery_options.h b/connections/discovery_options.h index 44e23b75..1f5ae108 100644 --- a/connections/discovery_options.h +++ b/connections/discovery_options.h @@ -29,6 +29,12 @@ namespace connections { // Connection Options: used for both Advertising and Discovery. // All fields are mutable, to make the type copy-assignable. struct DiscoveryOptions : OptionsBase { + // Returns a copy and normalizes allowed mediums: + // (1) If is_out_of_band_connection is true, verifies that there is only one + // medium allowed, defaulting to only Bluetooth if unspecified. + // (2) If no mediums are allowed, allow all mediums. + DiscoveryOptions CompatibleOptions() const; + bool auto_upgrade_bandwidth; bool enforce_topology_constraints; int keep_alive_interval_millis = 0; @@ -36,14 +42,12 @@ struct DiscoveryOptions : OptionsBase { // Whether this is intended to be used in conjunction with InjectEndpoint(). bool is_out_of_band_connection = false; + // TODO(b/229927044): Replaces it as bool once Ble v1 is deprecated. std::string fast_advertisement_service_uuid; - // Returns a copy and normalizes allowed mediums: - // (1) If is_out_of_band_connection is true, verifies that there is only one - // medium allowed, defaulting to only Bluetooth if unspecified. - // (2) If no mediums are allowed, allow all mediums. - DiscoveryOptions CompatibleOptions() const; + // If true, only low power mediums (like BLE) will be used for discovery. + bool low_power = false; }; } // namespace connections diff --git a/connections/implementation/base_pcp_handler.h b/connections/implementation/base_pcp_handler.h index 8499124a..7b9b47ca 100644 --- a/connections/implementation/base_pcp_handler.h +++ b/connections/implementation/base_pcp_handler.h @@ -197,9 +197,18 @@ class BasePcpHandler : public PcpHandler, BleEndpoint(DiscoveredEndpoint endpoint, BlePeripheral peripheral) : DiscoveredEndpoint(std::move(endpoint)), ble_peripheral(std::move(peripheral)) {} + BlePeripheral ble_peripheral; }; + struct BleV2Endpoint : public BasePcpHandler::DiscoveredEndpoint { + BleV2Endpoint(DiscoveredEndpoint endpoint, BleV2Peripheral peripheral) + : DiscoveredEndpoint(std::move(endpoint)), + ble_peripheral(std::move(peripheral)) {} + + BleV2Peripheral ble_peripheral; + }; + struct WifiLanEndpoint : public DiscoveredEndpoint { WifiLanEndpoint(DiscoveredEndpoint endpoint, const NsdServiceInfo& service_info) diff --git a/connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h b/connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h index 042f0a43..6b908505 100644 --- a/connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h +++ b/connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h @@ -27,17 +27,19 @@ namespace nearby { namespace connections { namespace mediums { -/** Callback that is invoked when a {@link BlePeripheral} is discovered. */ +// Callback that is invoked when a {@link BlePeripheral} is discovered. struct DiscoveredPeripheralCallback { std::function peripheral_discovered_cb = DefaultCallback(); - std::function - peripheral_lost_cb = - DefaultCallback(); + std::function + peripheral_lost_cb = DefaultCallback(); }; } // namespace mediums diff --git a/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.cc b/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.cc index a560c637..11b4e228 100644 --- a/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.cc +++ b/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.cc @@ -109,7 +109,9 @@ void DiscoveredPeripheralTracker::ProcessLostGattAdvertisements() { if (lost_peripheral.IsValid()) { lost_peripheral.SetId(ByteArray(gatt_advertisement)); discovered_peripheral_callback.peripheral_lost_cb( - std::move(lost_peripheral), service_id); + std::move(lost_peripheral), service_id, + gatt_advertisement.GetData(), + gatt_advertisement.IsFastAdvertisement()); } } ClearGattAdvertisement(gatt_advertisement); diff --git a/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker_test.cc b/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker_test.cc index 7c3fa66e..8d6f2b57 100644 --- a/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker_test.cc +++ b/connections/implementation/mediums/ble_v2/discovered_peripheral_tracker_test.cc @@ -625,7 +625,9 @@ TEST_F(DiscoveredPeripheralTrackerTest, }, .peripheral_lost_cb = [&lost_latch, &lost_callback_times]( - BleV2Peripheral peripheral, const std::string& service_id) { + BleV2Peripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_callback_times++; lost_latch.CountDown(); }, @@ -689,10 +691,10 @@ TEST_F(DiscoveredPeripheralTrackerTest, found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&lost_latch]( + BleV2Peripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_latch.CountDown(); }, }, std::string(kFastAdvertisementServiceUuid)); @@ -750,10 +752,10 @@ TEST_F(DiscoveredPeripheralTrackerTest, LostPeripheralForAdvertisementLost) { found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&lost_latch]( + BleV2Peripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_latch.CountDown(); }, }, ""); @@ -811,10 +813,10 @@ TEST_F(DiscoveredPeripheralTrackerTest, found_latch_a.CountDown(); }, .peripheral_lost_cb = - [&lost_latch_a](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch_a.CountDown(); - }, + [&lost_latch_a]( + BleV2Peripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_latch_a.CountDown(); }, }, std::string(kFastAdvertisementServiceUuid)); discovered_peripheral_tracker_.StartTracking( @@ -830,10 +832,10 @@ TEST_F(DiscoveredPeripheralTrackerTest, found_latch_b.CountDown(); }, .peripheral_lost_cb = - [&lost_latch_b](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch_b.CountDown(); - }, + [&lost_latch_b]( + BleV2Peripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_latch_b.CountDown(); }, }, ""); @@ -896,10 +898,10 @@ TEST_F(DiscoveredPeripheralTrackerTest, found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&lost_latch]( + BleV2Peripheral peripheral, const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement) { lost_latch.CountDown(); }, }, ""); diff --git a/connections/implementation/mediums/ble_v2_test.cc b/connections/implementation/mediums/ble_v2_test.cc index 7b94629a..d87db2e7 100644 --- a/connections/implementation/mediums/ble_v2_test.cc +++ b/connections/implementation/mediums/ble_v2_test.cc @@ -269,10 +269,10 @@ TEST_F(BleV2Test, StartFastScanningDiscoverAndLostPeripheral) { found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&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()); @@ -318,10 +318,10 @@ TEST_F(BleV2Test, found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&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()); @@ -364,10 +364,10 @@ TEST_F(BleV2Test, StartScanningDiscoverAndLostPeripheral) { found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&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()); @@ -412,10 +412,10 @@ TEST_F(BleV2Test, StartScanningDiscoverButNoPeripheralLostAfterStopScanning) { found_latch.CountDown(); }, .peripheral_lost_cb = - [&lost_latch](BleV2Peripheral peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, + [&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()); diff --git a/connections/implementation/mediums/mediums.cc b/connections/implementation/mediums/mediums.cc index 3536c89c..051562b3 100644 --- a/connections/implementation/mediums/mediums.cc +++ b/connections/implementation/mediums/mediums.cc @@ -24,6 +24,8 @@ BluetoothClassic& Mediums::GetBluetoothClassic() { return bluetooth_classic_; } Ble& Mediums::GetBle() { return ble_; } +BleV2& Mediums::GetBleV2() { return ble_v2_; } + WifiLan& Mediums::GetWifiLan() { return wifi_lan_; } WifiHotspot& Mediums::GetWifiHotspot() { return wifi_hotspot_; } diff --git a/connections/implementation/mediums/mediums.h b/connections/implementation/mediums/mediums.h index 4031ae7a..28a9c95c 100644 --- a/connections/implementation/mediums/mediums.h +++ b/connections/implementation/mediums/mediums.h @@ -16,6 +16,7 @@ #define CORE_INTERNAL_MEDIUMS_MEDIUMS_H_ #include "connections/implementation/mediums/ble.h" +#include "connections/implementation/mediums/ble_v2.h" #include "connections/implementation/mediums/bluetooth_classic.h" #include "connections/implementation/mediums/bluetooth_radio.h" #ifdef NO_WEBRTC @@ -45,6 +46,9 @@ class Mediums { // Returns a handle to the Ble medium. Ble& GetBle(); + // Returns a handle to the Ble medium. + BleV2& GetBleV2(); + // Returns a handle to the Wifi-Lan medium. WifiLan& GetWifiLan(); @@ -66,6 +70,7 @@ class Mediums { BluetoothRadio bluetooth_radio_; BluetoothClassic bluetooth_classic_{bluetooth_radio_}; Ble ble_{bluetooth_radio_}; + BleV2 ble_v2_{bluetooth_radio_}; WifiLan wifi_lan_; WifiHotspot wifi_hotspot_; mediums::WebRtc webrtc_; diff --git a/connections/implementation/p2p_cluster_pcp_handler.cc b/connections/implementation/p2p_cluster_pcp_handler.cc index caa02cbf..a97341bb 100644 --- a/connections/implementation/p2p_cluster_pcp_handler.cc +++ b/connections/implementation/p2p_cluster_pcp_handler.cc @@ -14,6 +14,10 @@ #include "connections/implementation/p2p_cluster_pcp_handler.h" +#include +#include +#include + #include "absl/functional/bind_front.h" #include "absl/strings/escaping.h" #include "connections/implementation/base_pcp_handler.h" @@ -57,6 +61,7 @@ P2pClusterPcpHandler::P2pClusterPcpHandler( bluetooth_radio_(mediums->GetBluetoothRadio()), bluetooth_medium_(mediums->GetBluetoothClassic()), ble_medium_(mediums->GetBle()), + ble_v2_medium_(mediums->GetBleV2()), wifi_lan_medium_(mediums->GetWifiLan()), wifi_hotspot_medium_(mediums->GetWifiHotspot()), webrtc_medium_(mediums->GetWebRtc()), @@ -77,9 +82,16 @@ P2pClusterPcpHandler::GetConnectionMediumsByPriority() { if (bluetooth_medium_.IsAvailable()) { mediums.push_back(proto::connections::BLUETOOTH); } - if (ble_medium_.IsAvailable()) { - mediums.push_back(proto::connections::BLE); + if (FeatureFlags::GetInstance().GetFlags().support_ble_v2) { + if (ble_v2_medium_.IsAvailable()) { + mediums.push_back(proto::connections::BLE); + } + } else { + if (ble_medium_.IsAvailable()) { + mediums.push_back(proto::connections::BLE); + } } + return mediums; } @@ -120,13 +132,24 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( } if (advertising_options.allowed.ble) { - proto::connections::Medium ble_medium = StartBleAdvertising( - client, service_id, local_endpoint_id, local_endpoint_info, - advertising_options, web_rtc_state); - if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOGS(INFO) - << "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"; - mediums_started_successfully.push_back(ble_medium); + if (FeatureFlags::GetInstance().GetFlags().support_ble_v2) { + proto::connections::Medium ble_v2_medium = StartBleV2Advertising( + client, service_id, local_endpoint_id, local_endpoint_info, + advertising_options, web_rtc_state); + if (ble_v2_medium != proto::connections::UNKNOWN_MEDIUM) { + NEARBY_LOGS(INFO) + << "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"; + mediums_started_successfully.push_back(ble_v2_medium); + } + } else { + proto::connections::Medium ble_medium = StartBleAdvertising( + client, service_id, local_endpoint_id, local_endpoint_info, + advertising_options, web_rtc_state); + if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { + NEARBY_LOGS(INFO) + << "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"; + mediums_started_successfully.push_back(ble_medium); + } } } @@ -162,8 +185,13 @@ Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) { bluetooth_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); - ble_medium_.StopAdvertising(client->GetAdvertisingServiceId()); - ble_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); + if (FeatureFlags::GetInstance().GetFlags().support_ble_v2) { + ble_v2_medium_.StopAdvertising(client->GetAdvertisingServiceId()); + // TODO(b/213689498): Implements Stop accept connenction. + } else { + ble_medium_.StopAdvertising(client->GetAdvertisingServiceId()); + ble_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); + } wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId()); wifi_lan_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); @@ -534,6 +562,207 @@ void P2pClusterPcpHandler::BlePeripheralLostHandler( }); } +bool P2pClusterPcpHandler::IsRecognizedBleV2Endpoint( + absl::string_view service_id, const BleAdvertisement& advertisement) const { + if (!advertisement.IsValid()) { + NEARBY_LOGS(INFO) + << "BleAdvertisement doesn't conform to the format, discarding."; + return false; + } + + if (advertisement.GetVersion() != kBleAdvertisementVersion) { + NEARBY_LOGS(INFO) << "BleAdvertisement has an unknown version; expected " + << static_cast(kBleAdvertisementVersion) + << ", found " + << static_cast(advertisement.GetVersion()); + return false; + } + + if (advertisement.GetPcp() != GetPcp()) { + NEARBY_LOGS(INFO) << "BleAdvertisement doesn't match on Pcp; expected " + << PcpToStrategy(GetPcp()).GetName() << ", found " + << PcpToStrategy(advertisement.GetPcp()).GetName(); + return false; + } + + // Check ServiceId for normal advertisement. + // ServiceIdHash is empty for fast advertisement. + if (!advertisement.IsFastAdvertisement()) { + ByteArray expected_service_id_hash = GenerateHash( + std::string(service_id), BleAdvertisement::kServiceIdHashLength); + + if (advertisement.GetServiceIdHash() != expected_service_id_hash) { + NEARBY_LOGS(INFO) + << "BleAdvertisement doesn't match on expected service_id_hash; " + "expected " + << absl::BytesToHexString(expected_service_id_hash.data()) + << ", found " + << absl::BytesToHexString(advertisement.GetServiceIdHash().data()); + return false; + } + } + + return true; +} + +void P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler( + ClientProxy* client, BleV2Peripheral peripheral, + const std::string& service_id, const ByteArray& advertisement_bytes, + bool fast_advertisement) { + // TODO(edwinwu): Move the lambda to a named function. + RunOnPcpHandlerThread( + "p2p-ble-peripheral-discovered", + [this, client, peripheral = std::move(peripheral), service_id, + advertisement_bytes, fast_advertisement]() RUN_ON_PCP_HANDLER_THREAD() { + // Make sure we are still discovering before proceeding. + if (!client->IsDiscovering()) { + NEARBY_LOGS(WARNING) + << "Skipping discovery of BleAdvertisement header " + << absl::BytesToHexString(advertisement_bytes.data()) + << " because we are no longer discovering."; + return; + } + + // Parse the BLE advertisement bytes. + BleAdvertisement advertisement(fast_advertisement, advertisement_bytes); + + // Make sure the BLE advertisement points to a valid + // endpoint we're discovering. + if (!IsRecognizedBleV2Endpoint(service_id, advertisement)) return; + + // Report the discovered endpoint to the client. + // BleV2EndpointState ble_endpoint_state(/*ble=*/true, /*l2cap=*/false, + // /*bt=alse*/false); + BleV2EndpointState ble_endpoint_state; + ByteArray peripheral_id = peripheral.GetId(); + found_endpoints_in_ble_discover_cb_.insert( + {peripheral_id, ble_endpoint_state}); + + ble_endpoint_state.ble = true; + found_endpoints_in_ble_discover_cb_[peripheral_id] = ble_endpoint_state; + NEARBY_LOGS(INFO) << "Found BleAdvertisement " + << absl::BytesToHexString(advertisement_bytes.data()) + << " (with endpoint_id=" + << advertisement.GetEndpointId() + << ", and endpoint_info=" + << absl::BytesToHexString( + advertisement.GetEndpointInfo().data()) + << ")."; + OnEndpointFound( + client, + std::make_shared(BleV2Endpoint{ + {advertisement.GetEndpointId(), advertisement.GetEndpointInfo(), + service_id, proto::connections::Medium::BLE, + advertisement.GetWebRtcState()}, + std::move(peripheral), + })); + + // Make sure we can connect to this device via Classic Bluetooth. + std::string remote_bluetooth_mac_address = + advertisement.GetBluetoothMacAddress(); + if (remote_bluetooth_mac_address.empty()) { + NEARBY_LOGS(INFO) + << "No Bluetooth Classic MAC address found in advertisement."; + return; + } + + BluetoothDevice remote_bluetooth_device = + bluetooth_medium_.GetRemoteDevice(remote_bluetooth_mac_address); + if (!remote_bluetooth_device.IsValid()) { + NEARBY_LOGS(INFO) + << "A valid Bluetooth device could not be derived from the MAC " + "address " + << remote_bluetooth_mac_address; + return; + } + + ble_endpoint_state.bt = true; + found_endpoints_in_ble_discover_cb_[peripheral_id] = ble_endpoint_state; + OnEndpointFound(client, + std::make_shared(BluetoothEndpoint{ + { + advertisement.GetEndpointId(), + advertisement.GetEndpointInfo(), + service_id, + proto::connections::Medium::BLUETOOTH, + advertisement.GetWebRtcState(), + }, + remote_bluetooth_device, + })); + }); +} + +void P2pClusterPcpHandler::BleV2PeripheralLostHandler( + ClientProxy* client, BleV2Peripheral peripheral, + const std::string& service_id, const ByteArray& advertisement_bytes, + bool fast_advertisement) { + RunOnPcpHandlerThread( + "p2p-ble-peripheral-lost", + [this, client, service_id, peripheral = std::move(peripheral), + advertisement_bytes, fast_advertisement]() RUN_ON_PCP_HANDLER_THREAD() { + // Make sure we are still discovering before proceeding. + if (!client->IsDiscovering()) { + NEARBY_LOGS(WARNING) + << "Ignoring lost BlePeripheral " + << absl::BytesToHexString(peripheral.GetId().data()) + << " because we are no longer discovering."; + return; + } + + // Parse the BLE advertisement bytes. + BleAdvertisement advertisement(fast_advertisement, advertisement_bytes); + + // 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; + } + BleV2EndpointState ble_endpoint_state(item->second); + found_endpoints_in_ble_discover_cb_.erase(item); + + if (ble_endpoint_state.ble) { + // Report the lost endpoint to the client. + NEARBY_LOGS(INFO) + << "Lost BleEndpoint for BlePeripheral " + << absl::BytesToHexString(peripheral.GetId().data()) + << " (with endpoint_id=" << advertisement.GetEndpointId() + << " and endpoint_info=" + << absl::BytesToHexString(advertisement.GetEndpointInfo().data()) + << ")."; + OnEndpointLost(client, DiscoveredEndpoint{ + advertisement.GetEndpointId(), + advertisement.GetEndpointInfo(), + service_id, + proto::connections::Medium::BLE, + WebRtcState::kUndefined, + }); + } + if (ble_endpoint_state.bt) { + // Report the lost endpoint to the client. + NEARBY_LOGS(INFO) + << "Lost BluetoothEndpoint for BlePeripheral " + << absl::BytesToHexString(peripheral.GetId().data()) + << " (with endpoint_id=" << advertisement.GetEndpointId() + << " and endpoint_info=" + << absl::BytesToHexString(advertisement.GetEndpointInfo().data()) + << ")."; + OnEndpointLost(client, DiscoveredEndpoint{ + advertisement.GetEndpointId(), + advertisement.GetEndpointInfo(), + service_id, + proto::connections::Medium::BLUETOOTH, + WebRtcState::kUndefined, + }); + } + }); +} + bool P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint( const std::string& service_id, const WifiLanServiceInfo& wifi_lan_service_info) const { @@ -707,18 +936,39 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( } if (discovery_options.allowed.ble) { - proto::connections::Medium ble_medium = StartBleScanning( - { - .peripheral_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BlePeripheralDiscoveredHandler, this, - client), - .peripheral_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BlePeripheralLostHandler, this, client), - }, - client, service_id, discovery_options.fast_advertisement_service_uuid); - if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartDiscoveryImpl: Ble added"); - mediums_started_successfully.push_back(ble_medium); + if (FeatureFlags::GetInstance().GetFlags().support_ble_v2) { + proto::connections::Medium ble_v2_medium = StartBleV2Scanning( + { + .peripheral_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::BleV2PeripheralDiscoveredHandler, this, + client), + .peripheral_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::BleV2PeripheralLostHandler, this, + client), + }, + client, service_id, discovery_options); + if (ble_v2_medium != proto::connections::UNKNOWN_MEDIUM) { + NEARBY_LOGS(INFO) + << "P2pClusterPcpHandler::StartDiscoveryImpl: Ble added."; + mediums_started_successfully.push_back(ble_v2_medium); + } + } else { + proto::connections::Medium ble_medium = StartBleScanning( + { + .peripheral_discovered_cb = absl::bind_front( + &P2pClusterPcpHandler::BlePeripheralDiscoveredHandler, this, + client), + .peripheral_lost_cb = absl::bind_front( + &P2pClusterPcpHandler::BlePeripheralLostHandler, this, + client), + }, + client, service_id, + discovery_options.fast_advertisement_service_uuid); + if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { + NEARBY_LOGS(INFO) + << "P2pClusterPcpHandler::StartDiscoveryImpl: Ble added."; + mediums_started_successfully.push_back(ble_medium); + } } } @@ -751,7 +1001,11 @@ Status P2pClusterPcpHandler::StopDiscoveryImpl(ClientProxy* client) { << bluetooth_classic_discoverer_client_id_; } - ble_medium_.StopScanning(client->GetDiscoveryServiceId()); + if (FeatureFlags::GetInstance().GetFlags().support_ble_v2) { + ble_v2_medium_.StopScanning(client->GetDiscoveryServiceId()); + } else { + ble_medium_.StopScanning(client->GetDiscoveryServiceId()); + } return {Status::kSuccess}; } @@ -797,9 +1051,17 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::ConnectImpl( break; } case proto::connections::Medium::BLE: { - auto* ble_endpoint = down_cast(endpoint); - if (ble_endpoint) { - return BleConnectImpl(client, ble_endpoint); + if (FeatureFlags::GetInstance().GetFlags().support_ble_v2) { + auto* ble_v2_endpoint = down_cast(endpoint); + if (ble_v2_endpoint) { + return BleV2ConnectImpl(client, ble_v2_endpoint); + } + + } else { + auto* ble_endpoint = down_cast(endpoint); + if (ble_endpoint) { + return BleConnectImpl(client, ble_endpoint); + } } break; } @@ -853,7 +1115,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBluetoothAdvertising( std::string remote_device_name = socket.GetRemoteDevice().GetName(); auto channel = - absl::make_unique( + std::make_unique( service_id, /*channel_name=*/remote_device_name, socket); ByteArray remote_device_info{remote_device_name}; @@ -967,7 +1229,7 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BluetoothConnectImpl( }; } - auto channel = absl::make_unique( + auto channel = std::make_unique( endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, bluetooth_socket); NEARBY_LOGS(VERBOSE) << "Client" << client->GetClientId() @@ -1016,7 +1278,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( RUN_ON_PCP_HANDLER_THREAD() mutable { std::string remote_peripheral_name = socket.GetRemotePeripheral().GetName(); - auto channel = absl::make_unique( + auto channel = std::make_unique( service_id, /*channel_name=*/remote_peripheral_name, socket); ByteArray remote_peripheral_info = @@ -1070,7 +1332,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( std::string remote_device_name = socket.GetRemoteDevice().GetName(); auto channel = - absl::make_unique( + std::make_unique( service_id, /*channel_name=*/remote_device_name, socket); ByteArray remote_device_info{remote_device_name}; @@ -1130,8 +1392,8 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( NEARBY_LOGS(WARNING) << "In StartBleAdvertising(" << absl::BytesToHexString(local_endpoint_info.data()) << "), client=" << client->GetClientId() - << " failed to create an advertisement.", - ble_medium_.StopAcceptingConnections(service_id); + << " failed to create an advertisement."; + ble_medium_.StopAcceptingConnections(service_id); return proto::connections::UNKNOWN_MEDIUM; } @@ -1203,7 +1465,7 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleConnectImpl( }; } - auto channel = absl::make_unique( + auto channel = std::make_unique( endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, ble_socket); return BasePcpHandler::ConnectImplResult{ @@ -1213,6 +1475,171 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleConnectImpl( }; } +proto::connections::Medium P2pClusterPcpHandler::StartBleV2Advertising( + ClientProxy* client, const std::string& service_id, + const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, + const AdvertisingOptions& advertising_options, WebRtcState web_rtc_state) { + // Start listening for connections before advertising in case a connection + // request comes in very quickly. BLE allows connecting over BLE itself, as + // well as advertising the Bluetooth MAC address to allow connecting over + // Bluetooth Classic. + NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartBleAdvertising: service_id=" + << service_id << " : start"; + // TODO(b/213689498): Implements accept connenction. + PowerLevel power_level = advertising_options.low_power + ? PowerLevel::kLowPower + : PowerLevel::kHighPower; + if (ShouldAdvertiseBluetoothMacOverBle(power_level) || + ShouldAcceptBluetoothConnections(advertising_options)) { + if (bluetooth_medium_.IsAvailable() && + !bluetooth_medium_.IsAcceptingConnections(service_id)) { + if (!bluetooth_radio_.Enable() || + !bluetooth_medium_.StartAcceptingConnections( + service_id, {.accepted_cb = [this, client, local_endpoint_info]( + const std::string& service_id, + BluetoothSocket socket) { + if (!socket.IsValid()) { + NEARBY_LOGS(WARNING) + << "In BT StartAcceptingConnections.accepted_cb(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << ": Invalid socket in accept callback."; + return; + } + RunOnPcpHandlerThread( + "p2p-bt-on-incoming-connection", + [this, client, local_endpoint_info, service_id, + socket = std::move(socket)]() + RUN_ON_PCP_HANDLER_THREAD() mutable { + std::string remote_device_name = + socket.GetRemoteDevice().GetName(); + auto channel = + std::make_unique( + service_id, remote_device_name, socket); + ByteArray remote_device_info{remote_device_name}; + + OnIncomingConnection( + client, remote_device_info, std::move(channel), + proto::connections::Medium::BLUETOOTH); + }); + }})) { + NEARBY_LOGS(WARNING) + << "In BT StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " failed to start accepting for incoming BLE connections to " + "service_id=" + << service_id; + // TODO(b/213689498): Implements stop accepting connenction. + return proto::connections::UNKNOWN_MEDIUM; + } + NEARBY_LOGS(INFO) + << "In BT StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " started accepting for incoming BLE connections to service_id=" + << service_id; + } + } + + NEARBY_LOGS(INFO) << "In StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " start to generate BleAdvertisement with service_id=" + << service_id + << ", local endpoint_id=" << local_endpoint_id; + // Generate a BleAdvertisement. If a fast advertisement service UUID was + // provided, create a fast BleAdvertisement. + ByteArray advertisement_bytes; + bool fast_advertisement = + !advertising_options.fast_advertisement_service_uuid.empty(); + if (fast_advertisement) { + advertisement_bytes = ByteArray( + BleAdvertisement(kBleAdvertisementVersion, GetPcp(), local_endpoint_id, + local_endpoint_info, /*uwb_address=*/ByteArray{})); + } else { + const ByteArray service_id_hash = + GenerateHash(service_id, BleAdvertisement::kServiceIdHashLength); + std::string bluetooth_mac_address; + if (bluetooth_medium_.IsAvailable() && + ShouldAdvertiseBluetoothMacOverBle(power_level)) + bluetooth_mac_address = bluetooth_medium_.GetMacAddress(); + + advertisement_bytes = ByteArray(BleAdvertisement( + kBleAdvertisementVersion, GetPcp(), service_id_hash, local_endpoint_id, + local_endpoint_info, bluetooth_mac_address, /*uwb_address=*/ByteArray{}, + web_rtc_state)); + } + if (advertisement_bytes.Empty()) { + NEARBY_LOGS(WARNING) << "In StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " failed to create an advertisement."; + // TODO(b/213689498): Implements stop accepting connenction. + return proto::connections::UNKNOWN_MEDIUM; + } + + NEARBY_LOGS(INFO) << "In StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " generated BleAdvertisement with service_id=" + << service_id; + + if (!ble_v2_medium_.StartAdvertising( + service_id, advertisement_bytes, power_level, + !advertising_options.fast_advertisement_service_uuid.empty())) { + NEARBY_LOGS(WARNING) + << "In StartBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " couldn't start BLE Advertising with BleAdvertisement " + << absl::BytesToHexString(advertisement_bytes.data()); + // TODO(b/213689498): Implements stop accepting connenction. + return proto::connections::UNKNOWN_MEDIUM; + } + NEARBY_LOGS(INFO) << "In startBleAdvertising(" + << absl::BytesToHexString(local_endpoint_info.data()) + << "), client=" << client->GetClientId() + << " started BLE Advertising with BleAdvertisement " + << absl::BytesToHexString(advertisement_bytes.data()); + return proto::connections::BLE; +} + +proto::connections::Medium P2pClusterPcpHandler::StartBleV2Scanning( + BleV2DiscoveredPeripheralCallback callback, ClientProxy* client, + const std::string& service_id, const DiscoveryOptions& discovery_options) { + PowerLevel power_level = discovery_options.low_power ? PowerLevel::kLowPower + : PowerLevel::kHighPower; + if (bluetooth_radio_.Enable() && + ble_v2_medium_.StartScanning(service_id, power_level, + std::move(callback))) { + NEARBY_LOGS(INFO) + << "In StartBleScanning(), client=" << client->GetClientId() + << " started scanning for BLE advertisements for service_id=" + << service_id; + return proto::connections::BLE; + } + NEARBY_LOGS(INFO) << "In StartBleScanning(), client=" << client->GetClientId() + << " couldn't start scanning on BLE for service_id=" + << service_id; + + return proto::connections::UNKNOWN_MEDIUM; +} + +BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleV2ConnectImpl( + ClientProxy* client, BleV2Endpoint* endpoint) { + NEARBY_LOGS(VERBOSE) << "Client " << client->GetClientId() + << " is attempting to connect to endpoint(id=" + << endpoint->endpoint_id << ") over BLE."; + + // TODO(b/213689498): Implements connection. + return BasePcpHandler::ConnectImplResult{ + .medium = proto::connections::Medium::BLE, + .status = {Status::kBleError}, + .endpoint_channel = nullptr, + }; +} + proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( ClientProxy* client, const std::string& service_id, const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, @@ -1237,19 +1664,19 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( RunOnPcpHandlerThread( "p2p-wifi-on-incoming-connection", [this, client, local_endpoint_id, local_endpoint_info, - service_id, - socket = std::move( - socket)]() RUN_ON_PCP_HANDLER_THREAD() mutable { - std::string remote_service_name = local_endpoint_id; - auto channel = absl::make_unique( - service_id, /*channel_name=*/remote_service_name, - socket); - ByteArray remote_service_name_byte{remote_service_name}; + service_id, socket = std::move(socket)]() + RUN_ON_PCP_HANDLER_THREAD() mutable { + std::string remote_service_name = local_endpoint_id; + auto channel = std::make_unique( + service_id, /*channel_name=*/remote_service_name, + socket); + ByteArray remote_service_name_byte{remote_service_name}; - OnIncomingConnection(client, remote_service_name_byte, - std::move(channel), - proto::connections::Medium::WIFI_LAN); - }); + OnIncomingConnection( + client, remote_service_name_byte, + std::move(channel), + proto::connections::Medium::WIFI_LAN); + }); }})) { NEARBY_LOGS(WARNING) << "In StartWifiLanAdvertising(" @@ -1359,7 +1786,7 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WifiLanConnectImpl( }; } - auto channel = absl::make_unique( + auto channel = std::make_unique( endpoint->service_id, /*channel_name=*/endpoint->endpoint_id, socket); NEARBY_LOGS(INFO) << "Client " << client->GetClientId() << " created WifiLan endpoint channel to endpoint(id=" diff --git a/connections/implementation/p2p_cluster_pcp_handler.h b/connections/implementation/p2p_cluster_pcp_handler.h index b9478850..ccacef3c 100644 --- a/connections/implementation/p2p_cluster_pcp_handler.h +++ b/connections/implementation/p2p_cluster_pcp_handler.h @@ -110,9 +110,16 @@ class P2pClusterPcpHandler : public BasePcpHandler { ByteArray endpoint_info; }; + struct BleV2EndpointState { + bool ble = false; + bool l2cap = false; + bool bt = false; + }; + using BluetoothDiscoveredDeviceCallback = BluetoothClassic::DiscoveredDeviceCallback; using BleDiscoveredPeripheralCallback = Ble::DiscoveredPeripheralCallback; + using BleV2DiscoveredPeripheralCallback = BleV2::DiscoveredPeripheralCallback; using WifiLanDiscoveredServiceCallback = WifiLan::DiscoveredServiceCallback; static constexpr BluetoothDeviceName::Version kBluetoothDeviceNameVersion = @@ -151,8 +158,6 @@ class P2pClusterPcpHandler : public BasePcpHandler { ClientProxy* client, BluetoothEndpoint* endpoint); // Ble - // Maps a BlePeripheral to its corresponding BleEndpointState. - absl::flat_hash_map found_ble_endpoints_; bool IsRecognizedBleEndpoint(const std::string& service_id, const BleAdvertisement& advertisement) const; void BlePeripheralDiscoveredHandler(ClientProxy* client, @@ -174,6 +179,30 @@ class P2pClusterPcpHandler : public BasePcpHandler { BasePcpHandler::ConnectImplResult BleConnectImpl(ClientProxy* client, BleEndpoint* endpoint); + // BleV2 + bool IsRecognizedBleV2Endpoint(absl::string_view service_id, + const BleAdvertisement& advertisement) const; + void BleV2PeripheralDiscoveredHandler(ClientProxy* client, + BleV2Peripheral peripheral, + const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement); + void BleV2PeripheralLostHandler(ClientProxy* client, + BleV2Peripheral peripheral, + const std::string& service_id, + const ByteArray& advertisement_bytes, + bool fast_advertisement); + proto::connections::Medium StartBleV2Advertising( + ClientProxy* client, const std::string& service_id, + const std::string& local_endpoint_id, + const ByteArray& local_endpoint_info, + const AdvertisingOptions& advertising_options, WebRtcState web_rtc_state); + proto::connections::Medium StartBleV2Scanning( + BleV2DiscoveredPeripheralCallback callback, ClientProxy* client, + const std::string& service_id, const DiscoveryOptions& discovery_options); + BasePcpHandler::ConnectImplResult BleV2ConnectImpl(ClientProxy* client, + BleV2Endpoint* endpoint); + // WifiLan bool IsRecognizedWifiLanEndpoint( const std::string& service_id, @@ -197,12 +226,20 @@ class P2pClusterPcpHandler : public BasePcpHandler { BluetoothRadio& bluetooth_radio_; BluetoothClassic& bluetooth_medium_; Ble& ble_medium_; + BleV2& ble_v2_medium_; WifiLan& wifi_lan_medium_; WifiHotspot& wifi_hotspot_medium_; mediums::WebRtc& webrtc_medium_; InjectedBluetoothDeviceStore& injected_bluetooth_device_store_; std::int64_t bluetooth_classic_discoverer_client_id_{0}; std::int64_t bluetooth_classic_advertiser_client_id_{0}; + + // Maps a BlePeripheral to its corresponding BleEndpointState. + absl::flat_hash_map found_ble_endpoints_; + + // Maps a BlePeripheral.Id_ to its corresponding BleEndpointState. + absl::flat_hash_map + found_endpoints_in_ble_discover_cb_; }; } // namespace connections diff --git a/internal/platform/ble_v2.h b/internal/platform/ble_v2.h index d0d3a2b2..103944e8 100644 --- a/internal/platform/ble_v2.h +++ b/internal/platform/ble_v2.h @@ -175,6 +175,7 @@ class BleV2Medium final { bool IsValid() const { return impl_ != nullptr; } api::ble_v2::BleMedium* GetImpl() const { return impl_.get(); } + BluetoothAdapter& GetAdapter() { return adapter_; } private: Mutex mutex_; diff --git a/internal/platform/feature_flags.h b/internal/platform/feature_flags.h index a3fb9575..661289bc 100644 --- a/internal/platform/feature_flags.h +++ b/internal/platform/feature_flags.h @@ -46,6 +46,8 @@ class FeatureFlags { // necessary to properly support multiple BWU mediums, multiple service, and // multiple endpionts. bool support_multiple_bwu_mediums = true; + // Ble v2/v1 switch flag: the flag will be removed once v2 refactor is done. + bool support_ble_v2 = false; }; static const FeatureFlags& GetInstance() {