Add client-side connection APIs for ble l2cap

PiperOrigin-RevId: 741061740
This commit is contained in:
Mingshiou Wu
2025-03-27 01:38:10 -07:00
committed by Copybara-Service
parent 04b2f9cfc6
commit aefcc4a8b2
7 changed files with 102 additions and 2 deletions
+1
View File
@@ -159,6 +159,7 @@ cc_library(
"//connections/implementation/mediums:webrtc_utils",
"//connections/implementation/mediums/advertisements:dct_advertisement",
"//connections/implementation/mediums/advertisements:util",
"//connections/implementation/mediums/ble_v2:ble_advertisement_header",
"//connections/implementation/proto:offline_wire_formats_cc_proto",
"//connections/v3:v3_types",
"//internal/analytics:event_logger",
@@ -836,6 +836,43 @@ ErrorOr<BleV2Socket> BleV2::Connect(const std::string& service_id,
return socket;
}
ErrorOr<BleL2capSocket> BleV2::ConnectOverL2cap(
const std::string& service_id, const BleV2Peripheral& peripheral,
CancellationFlag* cancellation_flag) {
MutexLock lock(&mutex_);
if (service_id.empty()) {
LOG(WARNING) << "Refusing to create client Ble L2CAP socket because "
"service_id is empty.";
return {Error(OperationResultCode::NEARBY_LOCAL_CLIENT_STATE_WRONG)};
}
if (!IsAvailableLocked()) {
LOG(INFO) << "Can't create client Ble L2CAP socket [service_id="
<< service_id << "]; Ble isn't available.";
return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)};
}
if (cancellation_flag->Cancelled()) {
LOG(WARNING) << "Can't create client Ble L2CAP socket due to cancel.";
return {Error(OperationResultCode::
CLIENT_CANCELLATION_CANCEL_BLE_OUTGOING_CONNECTION)};
}
BleL2capSocket socket = medium_.ConnectOverL2cap(
service_id, PowerLevelToTxPowerLevel(PowerLevel::kHighPower), peripheral,
cancellation_flag);
if (!socket.IsValid()) {
LOG(WARNING) << "Failed to Connect via Ble L2CAP [service_id=" << service_id
<< "]";
return {Error(OperationResultCode::
CONNECTIVITY_L2CAP_CLIENT_SOCKET_CREATION_FAILURE)};
}
return socket;
}
bool BleV2::IsAvailableLocked() const { return medium_.IsValid(); }
bool BleV2::IsAdvertisingLocked(const std::string& service_id) const {
@@ -182,6 +182,13 @@ class BleV2 final {
CancellationFlag* cancellation_flag)
ABSL_LOCKS_EXCLUDED(mutex_);
// Establishes connection to Ble peripheral.
// Returns socket instance. On success, BleSocket.IsValid() return true.
ErrorOr<BleL2capSocket> ConnectOverL2cap(const std::string& service_id,
const BleV2Peripheral& peripheral,
CancellationFlag* cancellation_flag)
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true if this object owns a valid platform implementation.
bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
@@ -45,6 +45,7 @@
#include "connections/implementation/mediums/advertisements/advertisement_util.h"
#include "connections/implementation/mediums/advertisements/dct_advertisement.h"
#include "connections/implementation/mediums/ble_v2.h"
#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h"
#include "connections/implementation/mediums/bluetooth_classic.h"
#include "connections/implementation/mediums/mediums.h"
#include "connections/implementation/mediums/utils.h"
@@ -2715,6 +2716,36 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleV2ConnectImpl(
VLOG(1) << "Client " << client->GetClientId()
<< " is attempting to connect to (" << peripheral.ToReadableString()
<< ") over BLE.";
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::kEnableBleL2cap) &&
peripheral.GetPsm() !=
mediums::BleAdvertisementHeader::kDefaultPsmValue) {
ErrorOr<BleL2capSocket> ble_l2cap_socket_result =
ble_v2_medium_.ConnectOverL2cap(
endpoint->service_id, peripheral,
client->GetCancellationFlag(endpoint->endpoint_id));
if (!ble_l2cap_socket_result.has_error()) {
LOG(INFO) << "In BleV2ConnectImpl(), connected to Ble L2CAP device "
<< absl::BytesToHexString(peripheral.GetId().data())
<< " for endpoint(id=" << endpoint->endpoint_id << ").";
auto channel = std::make_unique<BleL2capEndpointChannel>(
endpoint->service_id, /*channel_name=*/endpoint->endpoint_id,
ble_l2cap_socket_result.value());
return BasePcpHandler::ConnectImplResult{
.medium = BLE,
.status = {Status::kSuccess},
.operation_result_code = OperationResultCode::DETAIL_SUCCESS,
.endpoint_channel = std::move(channel),
};
} else {
LOG(WARNING) << "In BleV2ConnectImpl(), failed to connect to Ble L2CAP "
"device "
<< absl::BytesToHexString(peripheral.GetId().data())
<< " for endpoint(id=" << endpoint->endpoint_id << ").";
}
}
ErrorOr<BleV2Socket> ble_socket_result = ble_v2_medium_.Connect(
endpoint->service_id, peripheral,
client->GetCancellationFlag(endpoint->endpoint_id));
+7
View File
@@ -268,6 +268,13 @@ BleV2Socket BleV2Medium::Connect(const std::string& service_id,
return socket;
}
BleL2capSocket BleV2Medium::ConnectOverL2cap(
const std::string& service_id, TxPowerLevel tx_power_level,
const BleV2Peripheral& peripheral, CancellationFlag* cancellation_flag) {
// TODO(mingshiouwu): Replace with a real implementation connecting flow.
return BleL2capSocket(peripheral, nullptr);
}
bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
return IsValid() && impl_->IsExtendedAdvertisementsAvailable();
}
+9 -2
View File
@@ -516,13 +516,20 @@ class BleV2Medium final {
// On Success, BleL2capServerSocket::IsValid() returns true.
BleL2capServerSocket OpenL2capServerSocket(const std::string& service_id);
// Returns a new BleLanSocket.
// On Success, BleLanSocket::IsValid() returns true.
// Returns a new BleV2Socket.
// On Success, BleV2Socket::IsValid() returns true.
BleV2Socket Connect(const std::string& service_id,
api::ble_v2::TxPowerLevel tx_power_level,
const BleV2Peripheral& peripheral,
CancellationFlag* cancellation_flag);
// Returns a new BleL2capSocket.
// On Success, BleL2capSocket::IsValid() returns true.
BleL2capSocket ConnectOverL2cap(const std::string& service_id,
api::ble_v2::TxPowerLevel tx_power_level,
const BleV2Peripheral& peripheral,
CancellationFlag* cancellation_flag);
bool IsExtendedAdvertisementsAvailable();
bool IsValid() const { return impl_ != nullptr; }
+10
View File
@@ -580,6 +580,16 @@ class BleMedium {
const std::string& service_id, TxPowerLevel tx_power_level,
BlePeripheral& peripheral, CancellationFlag* cancellation_flag) = 0;
// Connects to a BLE peripheral over L2CAP.
//
// On success, returns a new BleL2capSocket.
// On error, returns nullptr.
virtual std::unique_ptr<BleL2capSocket> ConnectOverL2cap(
const std::string& service_id, TxPowerLevel tx_power_level,
BlePeripheral& peripheral, CancellationFlag* cancellation_flag) {
return nullptr;
};
// Requests if support extended advertisement.
virtual bool IsExtendedAdvertisementsAvailable() = 0;