mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
added fast initiation manager and local test script for linux
This commit is contained in:
@@ -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)});
|
||||
}
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
@@ -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"],
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user