Support BLE injection.

PiperOrigin-RevId: 836431600
This commit is contained in:
Guogang Li
2025-11-24 18:19:49 -08:00
committed by Copybara-Service
parent 936cbe896b
commit 54f38cbf24
3 changed files with 165 additions and 27 deletions
@@ -1199,34 +1199,16 @@ Status P2pClusterPcpHandler::StopDiscoveryImpl(ClientProxy* client) {
Status P2pClusterPcpHandler::InjectEndpointImpl(
ClientProxy* client, const std::string& service_id,
const OutOfBandConnectionMetadata& metadata) {
LOG(INFO) << "InjectEndpoint.";
// Bluetooth is the only supported out-of-band connection medium.
if (metadata.medium != BLUETOOTH) {
LOG(WARNING) << "InjectEndpointImpl: Only Bluetooth is supported.";
return {Status::kError};
switch (metadata.medium) {
case BLUETOOTH:
return InjectBluetoothEndpoint(client, service_id, metadata);
case BLE:
return InjectBleEndpoint(client, service_id, metadata);
default:
LOG(WARNING) << "InjectEndpointImpl: medium "
<< Medium_Name(metadata.medium) << " is not supported.";
return {Status::kError};
}
// Make sure discovery is in out-of-band mode from the API definition in
// core.h.
if (!client->GetDiscoveryOptions().is_out_of_band_connection) {
LOG(WARNING) << "InjectEndpointImpl: Discovery is not in out-of-band mode.";
return {Status::kError};
}
BluetoothDevice remote_bluetooth_device =
injected_bluetooth_device_store_.CreateInjectedBluetoothDevice(
metadata.remote_bluetooth_mac_address, metadata.endpoint_id,
metadata.endpoint_info,
GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength),
GetPcp());
if (!remote_bluetooth_device.IsValid()) {
LOG(WARNING) << "InjectEndpointImpl: Invalid parameters.";
return {Status::kError};
}
BluetoothDeviceDiscoveredHandler(client, service_id, remote_bluetooth_device);
return {Status::kSuccess};
}
BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::ConnectImpl(
@@ -2878,5 +2860,91 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WifiLanConnectImpl(
};
}
Status P2pClusterPcpHandler::InjectBluetoothEndpoint(
ClientProxy* client, const std::string& service_id,
const OutOfBandConnectionMetadata& metadata) {
LOG(INFO) << "Inject Bluetooth endpoint for service_id=" << service_id;
// Make sure the medium is Bluetooth.
if (metadata.medium != BLUETOOTH) {
LOG(WARNING) << "InjectBluetoothEndpoint: Only Bluetooth is supported.";
return {Status::kError};
}
// Make sure discovery is in out-of-band mode from the API definition in
// core.h.
if (!client->GetDiscoveryOptions().is_out_of_band_connection) {
LOG(WARNING)
<< "InjectBluetoothEndpoint: Discovery is not in out-of-band mode.";
return {Status::kError};
}
BluetoothDevice remote_bluetooth_device =
injected_bluetooth_device_store_.CreateInjectedBluetoothDevice(
metadata.remote_bluetooth_mac_address, metadata.endpoint_id,
metadata.endpoint_info,
GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength),
GetPcp());
if (!remote_bluetooth_device.IsValid()) {
LOG(WARNING) << "InjectBluetoothEndpoint: Invalid parameters.";
return {Status::kError};
}
BluetoothDeviceDiscoveredHandler(client, service_id, remote_bluetooth_device);
return {Status::kSuccess};
}
Status P2pClusterPcpHandler::InjectBleEndpoint(
ClientProxy* client, const std::string& service_id,
const OutOfBandConnectionMetadata& metadata) {
LOG(INFO) << "Inject BLE endpoint for service_id=" << service_id;
if (!NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::
kEnableBleMediumInjection)) {
LOG(ERROR) << "InjectBleEndpoint: BLE injection is disabled.";
return {Status::kError};
}
if (metadata.medium != Medium::BLE) {
LOG(WARNING) << "InjectBleEndpoint: Only BLE is supported.";
return {Status::kError};
}
if (metadata.ble_peripheral_native_id.empty()) {
LOG(WARNING) << "InjectBleEndpoint: Invalid parameters.";
return {Status::kError};
}
if (!client->IsDiscovering()) {
LOG(WARNING)
<< "InjectBleEndpoint: Only allow injection when discovery is running.";
return {Status::kError};
}
std::optional<BlePeripheral> ble_peripheral =
ble_medium_.RetrieveBlePeripheralFromNativeId(
metadata.ble_peripheral_native_id);
if (!ble_peripheral.has_value()) {
LOG(WARNING) << "InjectBleEndpoint: Invalid peripheral native id.";
return {Status::kError};
}
ble_peripheral->SetPsm(metadata.psm);
RunOnPcpHandlerThread(
"p2p-bt-device-discovered",
[this, client, service_id, metadata, ble_peripheral = *ble_peripheral]()
RUN_ON_PCP_HANDLER_THREAD() {
OnEndpointFound(client,
std::make_shared<BleEndpoint>(BleEndpoint{
{metadata.endpoint_id, metadata.endpoint_info,
service_id, BLE, WebRtcState::kUndefined},
ble_peripheral}));
});
return {Status::kSuccess};
}
} // namespace connections
} // namespace nearby
@@ -42,12 +42,14 @@
#include "connections/implementation/mediums/wifi_direct.h"
#include "connections/implementation/mediums/wifi_hotspot.h"
#include "connections/implementation/mediums/wifi_lan.h"
#include "connections/implementation/webrtc_state.h"
#include "connections/medium_selector.h"
#include "connections/out_of_band_connection_metadata.h"
#include "connections/power_level.h"
#include "connections/status.h"
#include "connections/v3/connection_listening_options.h"
#include "internal/interop/device.h"
#include "internal/platform/awdl.h"
#include "internal/platform/ble.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/bluetooth_classic.h"
@@ -306,6 +308,13 @@ class P2pClusterPcpHandler : public BasePcpHandler {
BasePcpHandler::ConnectImplResult WifiLanConnectImpl(
ClientProxy* client, WifiLanEndpoint* endpoint);
// Endpoints injection.
Status InjectBluetoothEndpoint(ClientProxy* client,
const std::string& service_id,
const OutOfBandConnectionMetadata& metadata);
Status InjectBleEndpoint(ClientProxy* client, const std::string& service_id,
const OutOfBandConnectionMetadata& metadata);
Awdl& awdl_medium_;
BluetoothRadio& bluetooth_radio_;
BluetoothClassic& bluetooth_medium_;
@@ -1611,6 +1611,67 @@ TEST_F(P2pClusterPcpHandlerTest, CanConnectToInjectedEndpoint) {
env_.Stop();
}
TEST_F(P2pClusterPcpHandlerTest, CanInjectBleEndpoint) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableBleMediumInjection,
true);
env_.Start();
Mediums mediums_a;
EndpointChannelManager ecm_a;
EndpointManager em_a(&ecm_a);
BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {});
InjectedBluetoothDeviceStore ibds_a;
P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a);
DiscoveryOptions discovery_options{
{Strategy::kP2pCluster,
BooleanMediumSelector{
.ble = true,
}},
/* auto_upgrade_bandwidth= */ false,
/* enforce_topology_constraints= */ false,
/* is_out_of_band_connection= */ false,
};
CountDownLatch found_latch(1);
std::string found_endpoint_id;
EXPECT_EQ(
handler_a.StartDiscovery(&client_a_, service_id_, discovery_options,
{
.endpoint_found_cb =
[&](const std::string& endpoint_id,
const ByteArray& endpoint_info,
const std::string& service_id) {
found_endpoint_id = endpoint_id;
found_latch.CountDown();
},
}),
Status{Status::kSuccess});
std::string endpoint_id = "ABCD";
std::string endpoint_info_name = "endpoint_info";
ByteArray endpoint_info(endpoint_info_name);
OutOfBandConnectionMetadata metadata = {
.medium = location::nearby::proto::connections::Medium::BLE,
.endpoint_id = endpoint_id,
.ble_peripheral_native_id = mediums_a.GetBluetoothRadio()
.GetBluetoothAdapter()
.GetAddress()
.ToString(),
.psm = 1234,
};
handler_a.InjectEndpoint(&client_a_, service_id_, metadata);
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_EQ(found_endpoint_id, endpoint_id);
handler_a.StopDiscovery(&client_a_);
env_.Stop();
}
class P2pLostHandlerTestWithParam : public testing::TestWithParam<bool> {
protected:
void SetUp() override {