Add advertising logic for DCT

PiperOrigin-RevId: 733752366
This commit is contained in:
Guogang Li
2025-03-05 08:54:56 -08:00
committed by Copybara-Service
parent 18f52de400
commit 553f5dbf01
8 changed files with 185 additions and 34 deletions
+3
View File
@@ -119,6 +119,8 @@ cc_library(
"//connections/implementation/flags:connections_flags",
"//connections/implementation/mediums",
"//connections/implementation/mediums:utils",
"//connections/implementation/mediums/advertisements:dct_advertisement",
"//connections/implementation/mediums/advertisements:util",
"//connections/implementation/proto:offline_wire_formats_cc_proto",
"//connections/v3:v3_types",
"//internal/analytics:event_logger",
@@ -146,6 +148,7 @@ cc_library(
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:bind_front",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/random",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
@@ -17,6 +17,7 @@
#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <utility>
@@ -43,6 +44,7 @@
#include "connections/implementation/endpoint_channel_manager.h"
#include "connections/implementation/endpoint_manager.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/mediums/advertisements/advertisement_util.h"
#include "connections/implementation/mediums/mediums.h"
#include "connections/implementation/mediums/utils.h"
#include "connections/implementation/mediums/webrtc_peer_id.h"
@@ -249,6 +251,18 @@ Status BasePcpHandler::StartAdvertising(
}
}
if (client->IsDctEnabled()) {
// Update the device name.
std::optional<std::string> device_name =
nearby::connections::advertisements::ReadDeviceName(
info.endpoint_info);
if (device_name.has_value()) {
client->UpdateDctDeviceName(device_name.value());
} else {
LOG(ERROR) << "DCT only supports everyone mode for now.";
}
}
auto result = StartAdvertisingImpl(
client, service_id, client->GetLocalEndpointId(),
info.endpoint_info, compatible_advertising_options);
+68 -17
View File
@@ -28,9 +28,9 @@
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/functional/any_invocable.h"
#include "absl/random/random.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "connections/advertising_options.h"
#include "connections/connection_options.h"
@@ -39,6 +39,7 @@
#include "connections/implementation/analytics/analytics_recorder.h"
#include "connections/implementation/analytics/discovery_metadata_params.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/mediums/advertisements/dct_advertisement.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/payload.h"
@@ -107,6 +108,9 @@ ClientProxy::ClientProxy(::nearby::analytics::EventLogger* event_logger)
NEARBY_LOGS(INFO) << "[safe-to-disconnect]: Local enabled: "
<< supports_safe_to_disconnect_
<< "; Version: " << local_safe_to_disconnect_version_;
// Generate a 7 bits dedup value.
absl::BitGen bitgen;
dct_dedup_ = absl::Uniform(bitgen, 0, 1 << 7);
}
ClientProxy::~ClientProxy() { Reset(); }
@@ -115,24 +119,29 @@ std::int64_t ClientProxy::GetClientId() const { return client_id_; }
std::string ClientProxy::GetLocalEndpointId() {
MutexLock lock(&mutex_);
if (!local_endpoint_id_.empty()) {
NEARBY_LOGS(INFO) << __func__
<< ": Reusing cached endpoint id: " << local_endpoint_id_;
if (IsDctEnabled() && GetEndpointIdForDct().has_value()) {
NEARBY_LOGS(INFO) << "DCT is using genereted endpoint id.";
return GetEndpointIdForDct().value();
} else {
if (!local_endpoint_id_.empty()) {
NEARBY_LOGS(INFO) << __func__ << ": Reusing cached endpoint id: "
<< local_endpoint_id_;
return local_endpoint_id_;
}
if (external_device_provider_ == nullptr) {
local_endpoint_id_ = GenerateLocalEndpointId();
NEARBY_LOGS(INFO) << __func__ << ": Locally generating endpoint id: "
<< local_endpoint_id_;
} else {
local_endpoint_id_ =
external_device_provider_->GetLocalDevice()->GetEndpointId();
NEARBY_LOGS(INFO)
<< __func__
<< ": From external device provider, populating endpoint id: "
<< local_endpoint_id_;
}
return local_endpoint_id_;
}
if (external_device_provider_ == nullptr) {
local_endpoint_id_ = GenerateLocalEndpointId();
NEARBY_LOGS(INFO) << __func__ << ": Locally generating endpoint id: "
<< local_endpoint_id_;
} else {
local_endpoint_id_ =
external_device_provider_->GetLocalDevice()->GetEndpointId();
NEARBY_LOGS(INFO)
<< __func__
<< ": From external device provider, populating endpoint id: "
<< local_endpoint_id_;
}
return local_endpoint_id_;
}
const NearbyDevice* ClientProxy::GetLocalDevice() {
@@ -1301,6 +1310,48 @@ void ClientProxy::SetWebRtcNonCellular(bool webrtc_non_cellular) {
webrtc_non_cellular_ = webrtc_non_cellular;
}
bool ClientProxy::IsDctEnabled() const {
if (api::ImplementationPlatform::GetCurrentOS() != api::OSName::kApple) {
return false;
}
#if defined(NC_IOS_SDK)
return true;
#else
return false;
#endif
}
uint8_t ClientProxy::GetDctDedup() const { return dct_dedup_; }
void ClientProxy::UpdateDctDeviceName(absl::string_view device_name) {
if (!dct_device_name_.empty() && dct_device_name_ != device_name) {
// Need to update dedup value if device name is changed.
absl::BitGen bitgen;
dct_dedup_ = absl::Uniform(bitgen, 0, 1 << 7);
}
dct_device_name_ = device_name;
// The DCT endpoint ID should be derived from device name and dedup value.
std::optional<std::string> dct_endpoint_id =
advertisements::ble::DctAdvertisement::GenerateEndpointId(
dct_dedup_, dct_device_name_);
if (dct_endpoint_id.has_value()) {
dct_endpoint_id_ = *dct_endpoint_id;
} else {
dct_endpoint_id_.clear();
}
}
std::optional<std::string> ClientProxy::GetEndpointIdForDct() const {
if (dct_endpoint_id_.empty()) {
return std::nullopt;
}
return dct_endpoint_id_;
}
std::string ClientProxy::ToString(PayloadProgressInfo::Status status) const {
switch (status) {
case PayloadProgressInfo::Status::kSuccess:
+20
View File
@@ -339,6 +339,17 @@ class ClientProxy final {
// Sets the WebRTC non cellular network status.
void SetWebRtcNonCellular(bool webrtc_non_cellular);
// Returns true if DCT advertising/scanning is enabled.
bool IsDctEnabled() const;
// Gets the DCT dedup value. This is used to dedup the same device name when
// scanning for multiple devices.
// It is 7 bits derived from the local endpoint ID.
uint8_t GetDctDedup() const;
// Updates the DCT device name before advertising.
void UpdateDctDeviceName(absl::string_view device_name);
/** Bitmask for bt multiplex connection support. */
// Note. Deprecates the first and second bit of BT_MULTIPLEX_ENABLED and
// WIFI_LAN_MULTIPLEX_ENABLED and shift them to the third and the forth bit.
@@ -436,6 +447,15 @@ class ClientProxy final {
std::string ToString(PayloadProgressInfo::Status status) const;
std::optional<std::string> GetEndpointIdForDct() const;
// The device name used for DCT advertising.
std::string dct_device_name_;
// The dedup value used for DCT advertising.
uint8_t dct_dedup_ = 0;
// The endpoint ID used for DCT advertising.
std::string dct_endpoint_id_;
mutable RecursiveMutex mutex_;
std::int64_t client_id_;
std::string local_endpoint_id_;
@@ -22,7 +22,6 @@ cc_library(
name = "common",
srcs = ["data_element.cc"],
hdrs = ["data_element.h"],
compatible_with = ["//buildenv/target:non_prod"],
deps = [
"//internal/platform:base",
"//internal/platform:logging",
@@ -35,7 +34,6 @@ cc_library(
name = "dct_advertisement",
srcs = ["dct_advertisement.cc"],
hdrs = ["dct_advertisement.h"],
compatible_with = ["//buildenv/target:non_prod"],
deps = [
":common",
"//internal/crypto_cros",
@@ -51,7 +49,6 @@ cc_library(
name = "util",
srcs = ["advertisement_util.cc"],
hdrs = ["advertisement_util.h"],
compatible_with = ["//buildenv/target:non_prod"],
deps = [
":dct_advertisement",
"//internal/platform:base",
+39 -6
View File
@@ -149,6 +149,27 @@ ErrorOr<bool> BleV2::StartAdvertising(const std::string& service_id,
return {Error(OperationResultCode::MEDIUM_UNAVAILABLE_BLE_NOT_AVAILABLE)};
}
if (advertising_type == AdvertisingType::kDct) {
advertising_infos_.insert(
{service_id, AdvertisingInfo{.dct_advertisement = advertisement_bytes,
.power_level = power_level,
.advertising_type = advertising_type}});
if (!StartDctAdvertisingLocked(service_id, power_level,
advertisement_bytes)) {
LOG(ERROR) << "Failed to start BLE DCT advertising for service_id="
<< service_id;
advertising_infos_.erase(service_id);
return {Error(
OperationResultCode::CONNECTIVITY_BLE_START_ADVERTISING_FAILURE)};
}
LOG(INFO) << "Successfully started BLE DCT advertising for service_id="
<< service_id << " with advetsiement data "
<< absl::BytesToHexString(advertisement_bytes.AsStringView());
return {true};
}
// Wrap the connections advertisement to the medium advertisement.
ByteArray service_id_hash = mediums::bleutils::GenerateHash(
service_id, mediums::BleAdvertisement::kServiceIdHashLength);
@@ -171,11 +192,9 @@ ErrorOr<bool> BleV2::StartAdvertising(const std::string& service_id,
}
advertising_infos_.insert(
{service_id,
AdvertisingInfo{.medium_advertisement = medium_advertisement,
.power_level = power_level,
.is_fast_advertisement =
advertising_type == AdvertisingType::kFast}});
{service_id, AdvertisingInfo{.medium_advertisement = medium_advertisement,
.power_level = power_level,
.advertising_type = advertising_type}});
// TODO(hais): need to update here after cros support RAII StartAdvertising.
// After all platforms support RAII StartAdvertising, then we can stop
@@ -908,7 +927,7 @@ bool BleV2::StartAdvertisingLocked(const std::string& service_id) {
}
const AdvertisingInfo& info = it->second;
if (info.is_fast_advertisement) {
if (info.advertising_type == AdvertisingType::kFast) {
return StartFastAdvertisingLocked(service_id, info.power_level,
info.medium_advertisement);
} else {
@@ -1078,6 +1097,20 @@ bool BleV2::StartGattAdvertisingLocked(
return true;
}
bool BleV2::StartDctAdvertisingLocked(const std::string& service_id,
PowerLevel power_level,
const ByteArray& dct_advertisement) {
BleAdvertisementData advertising_data;
advertising_data.is_extended_advertisement = false;
advertising_data.service_data.insert(
{mediums::bleutils::kDctServiceUuid, dct_advertisement});
return medium_.StartAdvertising(
advertising_data,
{.tx_power_level = PowerLevelToTxPowerLevel(power_level),
.is_connectable = false});
}
bool BleV2::StartAsyncScanningLocked(absl::string_view service_id,
PowerLevel power_level) {
CHECK(FeatureFlags::GetInstance().GetFlags().enable_ble_v2_async_scanning);
+6 -1
View File
@@ -166,8 +166,9 @@ class BleV2 final {
private:
struct AdvertisingInfo {
mediums::BleAdvertisement medium_advertisement;
ByteArray dct_advertisement;
PowerLevel power_level;
bool is_fast_advertisement;
AdvertisingType advertising_type;
};
// Same as IsAvailable(), but must be called with `mutex_` held.
@@ -230,6 +231,10 @@ class BleV2 final {
const ByteArray& medium_advertisement_bytes,
bool extended_advertisement_advertised)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool StartDctAdvertisingLocked(const std::string& service_id,
PowerLevel power_level,
const ByteArray& dct_advertisement)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Called by StartScanning when using the async methods.
bool StartAsyncScanningLocked(absl::string_view service_id,
PowerLevel power_level)
@@ -16,7 +16,9 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -39,6 +41,8 @@
#include "connections/implementation/endpoint_manager.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/injected_bluetooth_device_store.h"
#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/bluetooth_classic.h"
#include "connections/implementation/mediums/mediums.h"
@@ -2538,7 +2542,24 @@ ErrorOr<Medium> P2pClusterPcpHandler::StartBleV2Advertising(
local_endpoint_info, bluetooth_mac_address,
/*uwb_address=*/ByteArray{}, web_rtc_state));
}
if (advertisement_bytes.Empty()) {
ByteArray dct_advertisement_bytes;
if (client->IsDctEnabled()) {
// Try to read device name from local_endpoint_info.
std::optional<std::string> device_name =
advertisements::ReadDeviceName(local_endpoint_info);
// TODO(b/399740422): Get the real PSM from the L2CAP medium.
uint16_t psm = 0x11;
if (device_name.has_value()) {
std::optional<advertisements::ble::DctAdvertisement> dct_advertisement =
advertisements::ble::DctAdvertisement::Create(
service_id, *device_name, psm, client->GetDctDedup());
if (dct_advertisement.has_value()) {
dct_advertisement_bytes = ByteArray(dct_advertisement->ToData());
}
}
}
if (advertisement_bytes.Empty() && dct_advertisement_bytes.Empty()) {
LOG(WARNING) << "In StartBleV2Advertising("
<< absl::BytesToHexString(local_endpoint_info.data())
<< "), client=" << client->GetClientId()
@@ -2552,12 +2573,19 @@ ErrorOr<Medium> P2pClusterPcpHandler::StartBleV2Advertising(
<< "), client=" << client->GetClientId()
<< " generated BleAdvertisement with service_id=" << service_id;
ErrorOr<bool> ble_v2_result = ble_v2_medium_.StartAdvertising(
service_id, power_level,
advertising_options.fast_advertisement_service_uuid.empty()
? BleV2::AdvertisingType::kRegular
: BleV2::AdvertisingType::kFast,
advertisement_bytes);
ErrorOr<bool> ble_v2_result = false;
if (dct_advertisement_bytes.Empty()) {
ble_v2_result = ble_v2_medium_.StartAdvertising(
service_id, power_level,
advertising_options.fast_advertisement_service_uuid.empty()
? BleV2::AdvertisingType::kRegular
: BleV2::AdvertisingType::kFast,
advertisement_bytes);
} else {
ble_v2_result = ble_v2_medium_.StartAdvertising(
service_id, power_level, BleV2::AdvertisingType::kDct,
dct_advertisement_bytes);
}
if (ble_v2_result.has_error()) {
LOG(WARNING) << "In StartBleV2Advertising("
<< absl::BytesToHexString(local_endpoint_info.data())