added fast initiation manager and local test script for linux

This commit is contained in:
Lasan Mahaliyana
2026-06-15 12:48:26 +05:30
parent 63f0f319c6
commit 3a2dd0aeb4
8 changed files with 430 additions and 6 deletions
@@ -43,14 +43,16 @@ LEAdvertisement::LEAdvertisement(
std::vector<uint8_t> data_bytes(data.size());
const auto* bytes = data.data();
service_uuids_.push_back(uuid_string);
if (is_extended_advertisement_){
service_uuids_.push_back(uuid_string);
}
// service_uuids_.push_back("0000FE2C-0000-1000-8000-00805F9B34FB");
// service_uuids_.push_back("0000FE2C-0000-1000-8000-00805F9B34FB");
for (size_t i = 0; i < data.size(); i++) {
data_bytes[i] = bytes[i];
}
// LOG(INFO)<< __func__ << ": " << uuid_string;
// LOG(INFO)<< __func__ << ": " << BytesToHexString(data_bytes);
LOG(INFO)<< __func__ << ": " << uuid_string;
LOG(INFO)<< __func__ << ": " << BytesToHexString(data_bytes);
service_data_.insert({uuid_string, std::move(sdbus::Variant(data_bytes))});
// service_data_.insert({"0000FE2C-0000-1000-8000-00805F9B34FB", std::move(data_bytes)});
}
+15
View File
@@ -14,9 +14,24 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
licenses(["notice"])
refresh_compile_commands(
name = "refresh_compile_commands_fast_initiation",
# Specify the targets of interest.
# For example, specify a dict of targets and any flags required to build.
targets = {
":nearby_fast_initiation": "",
},
# No need to add flags already in .bazelrc. They're automatically picked up.
# If you don't need flags, a list of targets is also okay, as is a single target string.
# Wildcard patterns, like //... for everything, *are* allowed here, just like a build.
# As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions
# And if you're working on a header-only library, specify a test or binary target that compiles it.
)
cc_library(
name = "nearby_fast_initiation",
srcs = [
+20 -2
View File
@@ -13,9 +13,27 @@
# limitations under the License.
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:defs.bzl", "cc_binary")
licenses(["notice"])
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
refresh_compile_commands(
name = "refresh_compile_commands_sharing_platform",
# Specify the targets of interest.
# For example, specify a dict of targets and any flags required to build.
targets = {
":platform": "",
},
# No need to add flags already in .bazelrc. They're automatically picked up.
# If you don't need flags, a list of targets is also okay, as is a single target string.
# Wildcard patterns, like //... for everything, *are* allowed here, just like a build.
# As are additional targets (+) and subtractions (-), like in bazel query https://docs.bazel.build/versions/main/query.html#expressions
# And if you're working on a header-only library, specify a test or binary target that compiles it.
)
cc_library(
name = "platform",
hdrs = [
@@ -43,8 +61,8 @@ cc_library(
"//internal/platform:mac_address",
"//internal/platform:types",
"//internal/platform/implementation:types",
"//location/nearby/sharing/lib/account:account_manager",
"//location/nearby/sharing/lib/sync:sync_binding_prefs_cc_proto",
#"//location/nearby/sharing/lib/account:account_manager",
#"//location/nearby/sharing/lib/sync:sync_binding_prefs_cc_proto",
"//sharing/proto:share_cc_proto",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/strings:string_view",
+24 -1
View File
@@ -24,7 +24,7 @@ refresh_compile_commands(
# Specify the targets of interest.
# For example, specify a dict of targets and any flags required to build.
targets = {
":nearby_sharing_api_shared": "-s --check_visibility=false --spawn_strategy=standalone --verbose_failures --cxxopt=-std=c++20 --host_cxxopt=-std=c++20 --cxxopt='-fvisibility-inlines-hidden'",
":linux_fast_init": "",
},
# No need to add flags already in .bazelrc. They're automatically picked up.
# If you don't need flags, a list of targets is also okay, as is a single target string.
@@ -33,6 +33,29 @@ refresh_compile_commands(
# And if you're working on a header-only library, specify a test or binary target that compiles it.
)
cc_library(
name = "linux_fast_init",
hdrs = [
"nearby_fast_init_ble_beacon.h",
"nearby_fast_init_manager.h",
],
srcs = [
"nearby_fast_init_manager.cc",
],
deps = [
"//sharing/internal/api:platform",
"//connections:core",
"//internal/platform/implementation/linux"
]
)
cc_binary(
name = "fast_init_test",
srcs = ["nearby_fast_init.cc"],
deps = [":linux_fast_init"]
)
cc_library(
name = "linux_sharing_platform",
srcs = ["platform/linux_sharing_platform.cc"],
+50
View File
@@ -0,0 +1,50 @@
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "sharing/linux/nearby_fast_init_ble_beacon.h"
#include "sharing/linux/nearby_fast_init_manager.h"
#include <thread>
#include <chrono>
// For local testing only. Android logs show that our fast init beacon is
// properly detected and they start advertising.
int main() {
auto system_bus = ::nearby::linux::getSystemBusConnection();
auto manager = ::nearby::linux::bluez::BluezObjectManager(*system_bus);
std::shared_ptr<nearby::linux::BluetoothAdapter> adapter;
auto interfaces = manager.GetManagedObjects();
for (auto& [object, properties] : interfaces) {
if (properties.count(sdbus::InterfaceName(
org::bluez::Adapter1_proxy::INTERFACE_NAME)) == 1) {
LOG(INFO) << __func__ << ": found bluetooth adapter " << object;
adapter = std::make_shared<::nearby::linux::BluetoothAdapter>(system_bus,
object);
}
}
auto beacon = ::nearby::sharing::linux::LinuxFastInitBleBeacon();
try {
auto interfaces = manager.GetManagedObjects();
for (auto& [object, properties] : interfaces) {
if (properties.count(sdbus::InterfaceName(
org::bluez::Adapter1_proxy::INTERFACE_NAME)) == 1) {
LOG(INFO) << __func__ << ": found bluetooth adapter " << object;
adapter = std::make_shared<::nearby::linux::BluetoothAdapter>(
system_bus, object);
}
}
} catch (const sdbus::Error& e) {
DBUS_LOG_METHOD_CALL_ERROR(&manager, "GetManagedObjects", e);
}
auto fast_init_manager =
::nearby::sharing::linux::LinuxFastInitiationManager(beacon, adapter);
fast_init_manager.StartAdvertising(
nearby::api::FastInitBleBeacon::FastInitType::kNotify, []() { return; },
[](nearby::api::FastInitiationManager::Error e) { return; });
std::this_thread::sleep_for(std::chrono::seconds(30));
return 0;
}
@@ -0,0 +1,87 @@
#include "sharing/internal/api/fast_init_ble_beacon.h"
namespace nearby {
namespace sharing {
namespace linux {
class LinuxFastInitBleBeacon final : public nearby::api::FastInitBleBeacon {
public:
void SerializeToByteArray() override {
std::array<uint8_t, nearby::api::FastInitBleBeacon::kAdvertiseDataTotalSize>
data{};
std::size_t offset = 0;
data[offset++] = nearby::api::FastInitBleBeacon::kFastInitServiceUuid[0];
data[offset++] = nearby::api::FastInitBleBeacon::kFastInitServiceUuid[1];
for (uint8_t byte : nearby::api::FastInitBleBeacon::kFastInitModelId) {
data[offset++] = byte;
}
const uint8_t metadata = (static_cast<uint8_t>(this->GetVersion()) << 5) |
(static_cast<uint8_t>(this->GetType()) << 2) |
(this->GetUwbSupported() ? 0x02 : 0x00) |
(this->GetSenderCertSupported() ? 0x01 : 0x00);
data[offset++] = metadata;
data[offset++] = static_cast<uint8_t>(this->GetAdjustedTxPower());
for (uint8_t byte : this->GetUwbMetadata()) {
data[offset++] = byte;
}
for (uint8_t byte : this->GetUwbAddress()) {
data[offset++] = byte;
}
for (uint8_t byte : this->GetSalt()) {
data[offset++] = byte;
}
for (uint8_t byte : this->GetSecretIdHash()) {
data[offset++] = byte;
}
data[offset++] = (this->GetRequireBtAdvertising() ? 0x80 : 0x00) |
(this->GetSelfOnlyAdvertising() ? 0x40 : 0x00);
SetAdDataByteArray(data);
}
void ParseFromByteArray() override {
const auto data = GetAdDataByteArray();
if (data[0] != nearby::api::FastInitBleBeacon::kFastInitServiceUuid[0] ||
data[1] != nearby::api::FastInitBleBeacon::kFastInitServiceUuid[1]) {
return;
}
const uint8_t metadata = data[5];
SetVersion(static_cast<FastInitVersion>((metadata >> 5) & 0x07));
SetType(static_cast<FastInitType>((metadata >> 2) & 0x07));
SetUwbSupported((metadata & 0x02) != 0);
SetSenderCertSupported((metadata & 0x01) != 0);
SetAdjustedTxPower(static_cast<int8_t>(data[6]));
std::array<uint8_t, kUwbMetadataSize> uwb_metadata{};
uwb_metadata[0] = data[7];
SetUwbMetadata(uwb_metadata);
std::array<uint8_t, kUwbAddressSize> uwb_address{};
for (std::size_t i = 0; i < uwb_address.size(); ++i) {
uwb_address[i] = data[8 + i];
}
SetUwbAddress(uwb_address);
std::array<uint8_t, kSaltSize> salt{};
salt[0] = data[16];
SetSalt(salt);
std::array<uint8_t, kSecretIdHashSize> secret_id_hash{};
for (std::size_t i = 0; i < secret_id_hash.size(); ++i) {
secret_id_hash[i] = data[17 + i];
}
SetSecretIdHash(secret_id_hash);
const uint8_t flags = data[25];
SetRequireBtAdvertising((flags & 0x80) != 0);
SetSelfOnlyAdvertising((flags & 0x40) != 0);
}
};
} // namespace linux
} // namespace sharing
} // namespace nearby
+142
View File
@@ -0,0 +1,142 @@
#include <functional>
#include "sharing/internal/api/fast_init_ble_beacon.h"
#include "sharing/internal/api/fast_initiation_manager.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "sharing/linux/nearby_fast_init_manager.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
namespace nearby {
namespace sharing {
namespace linux {
void LinuxFastInitiationManager::StartAdvertising(
nearby::api::FastInitBleBeacon::FastInitType type,
std::function<void()> callback,
std::function<void(nearby::api::FastInitiationManager::Error)>
error_callback) {
absl::MutexLock lock(&mutex_);
if (advertisement_ != nullptr) {
if (error_callback) {
error_callback(nearby::api::FastInitiationManager::Error::kResourceInUse);
}
return;
}
if (adapter_ == nullptr || !adapter_->IsEnabled()) {
if (error_callback) {
error_callback(nearby::api::FastInitiationManager::Error::
kBluetoothRadioUnavailable);
}
return;
}
if (adv_manager_ == nullptr) {
if (error_callback) {
error_callback(
nearby::api::FastInitiationManager::Error::kHardwareNotSupported);
}
return;
}
auto fast_init_uuid = Uuid::FromString(kFastInitServiceUuid);
if (!fast_init_uuid.has_value()) {
if (error_callback) {
error_callback(nearby::api::FastInitiationManager::Error::kUnknown);
}
return;
}
beacon_.SetVersion(nearby::api::FastInitBleBeacon::FastInitVersion::kV1);
beacon_.SetType(type);
beacon_.SetUwbSupported(false);
beacon_.SetSenderCertSupported(false);
beacon_.SetAdjustedTxPower(
45); // TODO: make this set the real value from adapter
beacon_.SetUwbMetadata({});
beacon_.SetUwbAddress({});
beacon_.SetSalt({});
beacon_.SetSecretIdHash({});
beacon_.SetRequireBtAdvertising(true);
beacon_.SetSelfOnlyAdvertising(false);
beacon_.SerializeToByteArray();
const auto ad_data = beacon_.GetAdDataByteArray();
nearby::api::ble::BleAdvertisementData advertising_data;
advertising_data.is_extended_advertisement = false;
advertising_data.service_data.insert(
{*fast_init_uuid,
nearby::ByteArray(reinterpret_cast<const char*>(ad_data.data() + 2),
ad_data.size() - 2)});
nearby::api::ble::AdvertiseParameters advertising_parameters{
.tx_power_level = nearby::api::ble::TxPowerLevel::kHigh,
.is_connectable = false,
};
advertisement_ =
::nearby::linux::bluez::LEAdvertisement::CreateLEAdvertisement(
*adapter_->GetConnection(), advertising_data, advertising_parameters);
try {
adv_manager_->RegisterAdvertisementSync(
advertisement_->getObject().getObjectPath(), {});
} catch (const sdbus::Error& e) {
advertisement_.reset();
if (error_callback) {
if (e.getName() == "org.bluez.Error.AlreadyExists") {
error_callback(
nearby::api::FastInitiationManager::Error::kResourceInUse);
} else if (e.getName() == "org.bluez.Error.NotPermitted") {
error_callback(
nearby::api::FastInitiationManager::Error::kDisabledByUser);
} else {
error_callback(nearby::api::FastInitiationManager::Error::kUnknown);
}
}
return;
}
if (callback) {
callback();
}
}
void LinuxFastInitiationManager::StopAdvertising(
std::function<void()> callback) {
absl::MutexLock lock(&mutex_);
if (advertisement_ != nullptr && adv_manager_ != nullptr) {
try {
adv_manager_->UnregisterAdvertisementSync(
advertisement_->getObject().getObjectPath());
} catch (const sdbus::Error& e) {
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_.get(),
"UnregisterAdvertisementSync", e);
}
advertisement_.reset();
}
if (callback) {
callback();
}
}
void StopScanning(std::function<void()> callback) {
if (callback) {
callback();
}
}
void LinuxFastInitiationManager::StartScanning(
std::function<void()> devices_discovered_callback,
std::function<void()> devices_not_discovered_callback,
std::function<void(nearby::api::FastInitiationManager::Error)>
error_callback) {
if (error_callback) {
error_callback(
nearby::api::FastInitiationManager::Error::kHardwareNotSupported);
}
}
} // namespace linux
} // namespace sharing
} // namespace nearby
+87
View File
@@ -0,0 +1,87 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LINUX_NEARBY_SHARING_INTERNAL_API_FAST_INITIATION_MANAGER_H_
#define LINUX_NEARBY_SHARING_INTERNAL_API_FAST_INITIATION_MANAGER_H_
#include <functional>
#include "sharing/internal/api/fast_init_ble_beacon.h"
#include "sharing/internal/api/fast_initiation_manager.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
constexpr char kFastInitServiceUuid[] = "0000fe2c-0000-1000-8000-00805f9b34fb";
namespace nearby {
namespace sharing {
namespace linux {
class LinuxFastInitiationManager final
: public nearby::api::FastInitiationManager {
public:
explicit LinuxFastInitiationManager(
nearby::api::FastInitBleBeacon& beacon,
std::shared_ptr<::nearby::linux::BluetoothAdapter> bluetooth_adapter)
: beacon_(beacon), adapter_(std::move(bluetooth_adapter)) {
if (adapter_ != nullptr) {
adv_manager_ =
std::make_unique<nearby::linux::bluez::LEAdvertisementManager>(
*adapter_->GetConnection(), *adapter_);
}
}
void StartAdvertising(
nearby::api::FastInitBleBeacon::FastInitType type,
std::function<void()> callback,
std::function<void(nearby::api::FastInitiationManager::Error)>
error_callback) override ;
void StopAdvertising(std::function<void()> callback) override;
void StartScanning(
std::function<void()> devices_discovered_callback,
std::function<void()> devices_not_discovered_callback,
std::function<void(nearby::api::FastInitiationManager::Error)>
error_callback) override ;
void StopScanning(std::function<void()> callback) override {
if (callback) {
callback();
}
}
bool IsAdvertising() override {
absl::MutexLock lock(&mutex_);
return advertisement_ != nullptr;
}
bool IsScanning() override { return false; }
private:
nearby::api::FastInitBleBeacon& beacon_;
std::shared_ptr<::nearby::linux::BluetoothAdapter> adapter_;
std::unique_ptr<::nearby::linux::bluez::LEAdvertisementManager> adv_manager_;
absl::Mutex mutex_;
std::unique_ptr<::nearby::linux::bluez::LEAdvertisement> advertisement_
ABSL_GUARDED_BY(mutex_);
};
} // namespace linux
} // namespace sharing
} // namespace nearby
#endif // LINUX_NEARBY_SHARING_INTERNAL_API_FAST_INITIATION_MANAGER_H_